When you call a polymorphic method at runtime, Java uses a special data structure to decide a method of which class needs to be called. This structure is set up at the time the object is constructed, before any of the user-supplied constructor and initializer code get executed.
When you create A a = new B()
, the data structure that says "when test()
is called, you need to call A.test()
or B.test()
" is prepared before the constructor of A
is entered. Since this structure is prepared for the B
class, it points to B.test()
, even though the calling code is inside A
's constructor. That is why you see "from B"
printed twice.
Note, however, that although technically your code will do what you want, logically it is a very poor decision. The reason why this code is bad has to do with the initialization sequence: imagine a test()
method that relies on private fields of B
being initialized in the constructor, like this:
class B extends A {
private final String greeting;
public B() {
greeting = "Hello";
}
void test() {
System.out.println(greeting + " from B");
}
}
One would expect to see "Hello from B"
being printed. However, you would see it only in the second call: at the time the first call is made, greeting
is still null
.
That is why you should avoid calling method overrides from inside a constructor: it breaks method's assumption that the object has been fully initialized, sometimes with rather unfortunate consequences.