I found this apparently odd behaviour in method-overriding/overloading of Java, that has been boggling my mind. The call in the Main() method prints out "B_A", while I would expect it to be "B_B".
package one;
public class A {
public void method(A a){ System.out.println("A_A"); }
public void method(B b) { System.out.println("A_B"); }
public void method(){ this.method(this); }
}
package one;
public class B extends A {
public void method(A a) { System.out.println("B_A"); }
public void method(B b) { System.out.println("B_B"); }
public void method(){ super.method(); }
public static void main(String[] args) {
B bb = new B();
bb.method(); //prints B_A, expected B_B
}
}
I break down the process as the following:
- The compiler selects method
method()of class B - During runtime, JVM calls method
method()of its superclass viasuper() <- this statement is wrong (thanks Alexey Romanov and pvg). Selection of methods, overloading-wise, is always done at compile time. That is, that method translates to .m(A) before runtime. At runtime, the proper overriding method is chosen.this.method(this)gets called from within class A, butthisrefers to an instance of class B, therefore translating to methodmethod(B b)of class B.- Why is the method
method(A a)of class B being invoked, instead?
My guess is that the JVM, when it selects a subclass method during runtime, starts looking up into a table of overloaded methods, where is a fixed precedence and the methods with a arguments of higher classes in the hierarchy are looked up first. That is, it doesn't go straight for B.method(B b), instead it looks it up into such a table and it's ok with the first compatible method - B.method(A a) - as B is A.
Another idea is that the call this.method(this) in class A calls B.method(A a) straight out, but that would imply that the same symbol (this) in the same context could refer to different objects.
Any help sorting this out? Thanks in advance!