I was very confused when I discovered that the fields initialization in Java has some strange order. Example code when init() result is overwritten by field initialization:
public abstract class Parent { public String parentField = "dupa"; public Parent(){ init(); // uhh, bad practice to call abstract method in a super constructor } protected abstract void init(); } public class Child extends Parent { public String childField = null; // assigning null is unnecessary, another bad practice @Override protected void init(){ childField = "initialized"; System.out.println("After init(): " + childField); } } ... Child child = new Child(); // OUTPUT: After init(): initialized System.out.println("After all: " + child.childField); // OUTPUT: After all: null I found out what is the execution order when invoking new Child();:
- Parent fields initialization, but childField already exists and has default value (childField = null)
- Parent constructor
- overridden init() called by parent constructor (childField = "initialized")
- Child fields initialization: childField = null (again)
- Child constructor
I know this example is full of bad practices. However, the intuitive order for me would be: fields initializations (from parents to childs), then constructors (from parents to childs).
What is the purpose of such initialization order? Why the fields initializers are not executed before their potential first use? If the field is not initialized yet, so why is it allowed to use it?
childFieldhappen in theChildbefore the ctor for theParenthad finished?superwill be completely constructed.