Reputation: 6107
Why does this code compile with explicit static field notation on the right hand side, but not without ?
public class A
{
static int a = ++A.a; // compiles
//static int a = ++a; // error - cannot reference a field before it is defined
public static void main(String[] args) {
System.out.println(a);
}
}
Upvotes: 9
Views: 386
Reputation: 16216
In addition to @Andy's answer I would like to show some examples that are taken from this JLS chapter. They explains the Use Before Declaration rules, demonstrating valid & invalid cases:
class UseBeforeDeclaration {
static {
int a = UseBeforeDeclaration.b + 2; // ok - 'b' is not accessed via simple name
}
{
c = 1000000; // ok - assignment
c = c + 100; // error - right hand side reads before declaration
int d = c++; // error - read before declaration
int e = this.c * 2; // ok - 'c' is not accessed via simple name
}
static int b;
int c;
}
Also, after the byte code investigation for the valid static int a = ++A.a
line, we can see that it is get compiled into:
static <clinit>()V
L0
LINENUMBER 4 L0
GETSTATIC src/java/A.a : I
ICONST_1
IADD
DUP
PUTSTATIC src/java/A.a : I
PUTSTATIC src/java/A.a : I
RETURN
Which is equivalent to:
public class A {
static int a;
static {
++a;
}
public static void main(String[] args) {
// ...
}
}
Upvotes: 1
Reputation: 140318
This is simply how the language spec is written. Specifically, Sec 8.3.3 says:
References to a field are sometimes restricted, even through the field is in scope. The following rules constrain forward references to a field (where the use textually precedes the field declaration) as well as self-reference (where the field is used in its own initializer).
For a reference by simple name to a class variable f declared in class or interface C, it is a compile-time error if:
- ...
Emphasis mine.
A.a
is not a simple name, so it's not a compile-time error.
Upvotes: 4