Consider these two classes:
public abstract class Bar {
protected Bar() {
System.out.println(getValue());
}
protected abstract int getValue();
}
public class Foo extends Bar {
private final int i = 20;
public Foo() {
}
@Override
protected int getValue() {
return i;
}
public static void main(String[] args) {
new Foo();
}
}
If I execute Foo, the output is 20.
If I make the field non-final, or if I initialize it in the Foo constructor, the output is 0.
My question is: what is the initialization order in case of final fields and where is this behavior described in the JLS?
I expected to find some exceptional rule about final fields here, but unless I miss something, there isn't.
Note that I know I should never call an overridable method from a constructor. That's not the point of the question.
Your final int i
member variable is a constant variable: 4.12.4. final
Variables
A variable of primitive type or type
String
, that isfinal
and initialized with a compile-time constant expression (§15.28), is called a constant variable.
This has consequences for the order in which things are initialized, as described in 12.4.2. Detailed Initialization Procedure.