Cannot reference "X" before supertype constructor has been called, where x is a final variable
Asked Answered
N

6

92

Consider the following Java class declaration:

public class Test {

    private final int defaultValue = 10;
    private int var;

    public Test() {
        this(defaultValue);    // <-- Compiler error: cannot reference defaultValue before supertype constructor has been called.
    }

    public Test(int i) {
        var = i;
    }
}

The code will not compile, with the compiler complaining about the line I've highlighted above. Why is this error happening and what's the best workaround?

Nefen answered 9/6, 2012 at 19:5 Comment(0)
N
116

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:

Nefen answered 9/6, 2012 at 19:6 Comment(4)
this is the correct answer , as this is how you declare constants on javaBassinet
So an object is created only after the constructor finishes?Pantechnicon
@Pantechnicon essentially, yes.Nefen
No, an object is created when the root constructor in the constructor chain (that is the Object class constructor) executes. It it were created only after (ordinary) constructor having finished, then its fields were unavailable during the constructor execution. In this example, the intermediate constructor Test(int i) references the field var, which already exists.Maltreat
D
9

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

Desert answered 9/6, 2012 at 19:8 Comment(0)
C
6

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;
    }
}
Coterminous answered 6/8, 2017 at 20:0 Comment(0)
P
4

Rule : Every constructor must execute super class's constructor before executing itself.

So the first line of every constructor is super() or may be this() and you are send the defaultValue to the this class constructor which(defaultValue) is not existed yet hence there is compile time error.

You can made defaultValue as static and since static variable is created as class is loaded to memory so defaultValue is available at the line this(defaultValue).

Pascual answered 9/6, 2012 at 19:42 Comment(0)
C
1

Until your object is not been constructed default values to the variables won't be set hence if you want their default values to be set at the time of construction make them static or explicitly set them before.

Chew answered 9/6, 2012 at 20:3 Comment(0)
E
0

constructor is called at the time of object creation so no reference to varable is recognized by compiler as compiler has no knowledge regarding instance variable as object is not created yet.

Enloe answered 14/6, 2017 at 10:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.