Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 321
Amr Bekhit Avatar asked Jun 09 '12 19:06

Amr Bekhit


People also ask

Why this () must be the first statement in constructor?

Java enforces that the call to super (explicit or not) must be the first statement in the constructor. This is to prevent the subclass part of the object being initialized prior to the superclass part of the object being initialized.

Does a constructor have to have the same name as its class?

The name of the constructor must be the same as the name of the class and, if you provide more than one constructor, the arguments to each constructor must differ in number or in type from the others. You do not specify a return value for a constructor.

What does a constructor do in Java?

A constructor in Java is a special method that is used to initialize objects. The constructor is called when an object of a class is created. It can be used to set initial values for object attributes. In Java, a constructor is a block of codes similar to the method.


2 Answers

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
like image 120
Amr Bekhit Avatar answered Sep 22 '22 04:09

Amr Bekhit


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

like image 29
jmj Avatar answered Sep 19 '22 04:09

jmj