Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does static field self assignment compile only with explicit static syntax?

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);
    }
}
like image 540
Gonen I Avatar asked Jan 08 '18 20:01

Gonen I


2 Answers

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.

like image 161
Andy Turner Avatar answered Oct 29 '22 20:10

Andy Turner


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) {
        // ...
    }
}
like image 1
Oleksandr Pyrohov Avatar answered Oct 29 '22 19:10

Oleksandr Pyrohov