Why when I use reference this
in a variable declaration, illegal forward reference doesn't appear? What's the difference between declaration with this
and without it?
The following example fails to compile because of the illegal forward reference:
class FailsToCompile {
int a = b; //illegal forward reference
int b = 10;
}
By qualifying the use of b
by this
the compilation error goes away.
class Compiles {
int a = this.b; //that's ok
int b = 10;
}
"Illegal forward reference" means that you are trying to use a variable before it is defined. The behavior you observe is a symptom of a javac bug(see this bug report). The problem appears to be fixed in newer versions of the compiler, e.g. OpenJDK 7.
Java allows very flexible forward references. A method may refer to a variable or another method of its class, regardless of where in the current class the variable or method is defined.
Assuming the following class
public class MyClass {
int a = b;
int b = 10;
}
The JLS 8.3.3. states in your case :
Use of instance variables whose declarations appear textually after the use is sometimes restricted
- The use is a simple name in either an instance variable initializer of C or an instance initializer of C
Now, using the member this
allows you to access an instance that is already declared with default values ( a = 0, b = 0
) but not yet fully initialized. This is visible if you check the result of:
public class MyClass {
int a = this.b;
int b = 10;
}
You would not get the expected value :
new MyClass().a //0
new MyClass().b //10
I can't explain why this is legal exactly since this would never give a correct value. We can find some explanation about why the restriction exist :
The restrictions above are designed to catch, at compile time, circular or otherwise malformed initializations.
But why allowing this
to works...
Knowing that during an initialization of an instance, the following actions occurs :
Give some strange behavior:
public class MyClass {
{
b = 10;
}
int a = this.b;
int b = 5;
{
b = 15;
}
public static void main(String[] args) {
MyClass m = new MyClass();
System.out.println(m.a); //10
System.out.println(m.b); //15
}
}
I would limit the initialization in the constructor.
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