To answer the direct question, it would call "Sub.m2". Here's a test case:
public class MyClass {
public static void main(String args[]) {
A test = new B();
test.m1();
}
public static class A {
void m1() { this.m2(); };
void m2() { System.out.println("Hello from A!"); }
}
public static class B extends A {
void m1() { super.m1(); }
void m2() { System.out.println("Hello from B!"); } //this is printed
}
}
Under the hood, the test
variable is always (short of reassignment) an instance of B
. The methods it inherits from A
are welcome to call methods inside of A
, but those methods in turn may be overridden by B
as well. If B#m2
had a super
call inside of it, you get even more information:
void m2() {
System.out.println("Hello from B!");
super.m2();
System.out.println("Hello again from B!");
}
This gives us the result:
Hello from B!
Hello from A!
Hello again from B!
From this, we can see that the most-specific version of #m2
is called. In other words, since test
is an instance of B
, it calls B#m2
first. From there, B#m2
can decide to call superclass methods, or completely replace the old functionality. If B
did not have an #m2
method, it would look to the parent classes of B
for such a method next.