Are fields initialized before constructor code is run in Java?
Can anyone explain the output of following program? I thought constructors are initialized before instance variables. So I was expecting the output to be "XZYY".
class X {
Y b = new Y();
X() {
System.out.print("X");
}
}
class Y {
Y() {
System.out.print("Y");
}
}
public class Z extends X {
Y y = new Y();
Z() {
System.out.print("Z");
}
public static void main(String[] args) {
new Z();
}
}
The correct order of initialisation is:
- Static variable initialisers and static initialisation blocks, in textual order, if the class hasn't been previously initialised.
- The super() call in the constructor, whether explicit or implicit.
- Instance variable initialisers and instance initialisation blocks, in textual order.
- Remaining body of constructor after super().
See sections §2.17.5-6 of the Java Virtual Machine Specification.
If you look at the decompiled version of the class file
class X {
Y b;
X() {
b = new Y();
System.out.print("X");
}
}
class Y {
Y() {
System.out.print("Y");
}
}
public class Z extends X {
Y y;
Z() {
y = new Y();
System.out.print("Z");
}
public static void main(String args[]) {
new Z();
}
}
You can find that the instance variable y
is moved inside the constructor, so the execution sequence is as follows
- Call the constructor of
Z
- It triggers the default constructor of
X
- First line of
X
constructornew Y()
is called. - Print Y
- Print X
- Call the first line in constructor Z
new Y()
- Print
Y
- Print Z
All the instance variables are initialized by using constructor statements.