Why is my field not being initialized with the value I gave it
I have the following classes:
public abstract class AClass {
public AClass() {
aMethod();
}
abstract protected void aMethod();
}
public class SubClass extends AClass {
private int x = 5;
private static final int y = 6;
@Override
protected void aMethod() {
System.out.println("x: " + x + " | y: " + y);
}
}
public class Main {
public static void main(String[] args) {
new SubClass();
}
}
Running Main prints the following: x: 0 | y: 6
Why is 0 printed for x?
source to share
The wrong behavior is caused by the wrong initialization sequence:
-
new SubClass()
executes the constructorAClass
-
AClass
constructor callsaMethod()
-
aMethod()
showsx
(so far0
) andy
which is6
due to static) -
SubClass
initializes its non-static fields, sox
it becomes5
.
To avoid surprises, never call virtual methods (esp. Overriden) in constructors
source to share
A static field is initialized as soon as the class is initialized (after loading). Now when you call
new SubClass()
the following events occur.
- The constructor
SubClass
is called as the first statementSubClass
(implicitly)- The constructor is called
SuperClass
. -> you are checking the valuex
here- Execution of the constructor
SuperClass
ends, then the instance-level fields areSubClass
initialized. So,x
will be initialized here.
source to share
The result is that the superclass's constructor is called before the elements are initialized.
In your case, the following sequence runs:
- Constructor call
SubClass
- immediate constructor call
AClass
- method call
aMethod()
- member initialization
SubClass
This is also the reason why you should not call any overridden methods from the constructor, as the called method can access the state of an object that is not fully initialized.
source to share
private static final int y = 6;
The y value is 6 when the constructor calls aMethod () because it is static and initialized when classes are loaded.
private int x = 5;
For now, this initialization is appended to the end of your constructor body. This means that when aMethod is executed, the x variable has a default value ie 0.
The default SubClass constructor would look like
SubClass() {
super();
//All instance initialization are performed here.
}
source to share