Cannot reference "X" before supertype constructor has been called, where x is a final variable
The reason why the code would not initially compile is because defaultValue
is an instance variable of the class Test
, meaning that when an object of type Test
is created, a unique instance of defaultValue
is also created and attached to that particular object. Because of this, it is not possible to reference defaultValue
in the constructor, as neither it, nor the object have been created yet.
The solution is to make the final variable static
:
public class Test {
private static final int defaultValue = 10;
private int var;
public Test() {
this(defaultValue);
}
public Test(int i) {
var = i;
}
}
By making the variable static
, it becomes associated with the class itself, rather than instances of that class and is shared amongst all instances of Test
. Static variables are created when the JVM first loads the class. Since the class is already loaded when you use it to create an instance, the static variable is ready to use and so can be used in the class, including the constructor.
References:
- Forum post asking the same question
- Understanding Instance and Class Members
- Explanation of how classloader loads static variables
It is because the defaultValue
is an member of Test
's instance which is under construction (not yet created)
If you had it static
it were loaded when your class loads by classloaders
You are referencing to a variable that doesn't exist yet, if it was static it would exist even before the constructor itself.
But you will face another problem, as defaultValue
became static, so all other instances may share the same value which you may don't like it to be:
public class Test {
private final int defaultValue = 10; //this will exist only after calling the constructor
private final static int value2= 10; //this exists before the constructor has been called
private int var;
public Test() {
// this(defaultValue); // this method will not work as defaultValue doesn't exist yet
this(value2); //will work
//this(10); will work
}
public Test(int i) {
var = i;
}
}