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.
In Java, the order for initialization statements is as follows: static variables and static initializers in order. instance variables and instance initializers in order. constructors.
If you declare a variable as final, it is mandatory to initialize it before the end of the constructor. If you don't, a compile-time error is generated.
If you declare a final variable later on you cannot modify or, assign values to it. Moreover, like instance variables, final variables will not be initialized with default values. Therefore, it is mandatory to initialize final variables once you declare them.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With