There are some properties of the Java language specification that should be noted in order to explain this behavior:
- A superclass' constructor is always implicitely/explicitely called before a subclass' constructor.
- A method call from a constructor is just like any other method call; if the method is a non-final, then the call is a virtual call, meaning that the method implementation to invoke is the one associated with the runtime type of the object.
- Prior to a constructor execution, all data members are automatically initialized with default values (0 for numeric primitives, null for objects, false for boolean).
The sequence of events is as follows:
- An instance of the subclass is created
- All data members are initialized with default values
- The constructor being invoked immediately delegates control to the relevant superclass' constructor.
- The super constructor initializes some/all of its own data members, and then calls a virtual method.
- The method is overriden by the subclass, so the subclass implementation is invoked.
- The method tries to use the subclass' data members, assuming they are already initialized, but this is not the case - the call stack hasn't returned to the subclass' constructor yet.
In short, whenever a constructor of a superclass invokes a non-final method, we have the potential risk of entering into this trap, therefore doing it is not recommended.
Note that there is no elegant solution if you insist on this pattern. Here are 2 complex and creative ones, both requiring thread synchronization(!):
http://www.javaspecialists.eu/archive/Issue086.html
http://www.javaspecialists.eu/archive/Issue086b.html