Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How a static variable is accessible before the declaration?

public class Main {

    static int x = Main.y;
//  static int x = y; //Not allowed; y is not defined
    static int y = x;
    public static void main(String[] args) {
        System.out.println(x);//prints 0
    }
}

How come I am allowed to use y trough the class, but not directly?

When is y defined?

like image 341
LarsErik Avatar asked Sep 13 '10 09:09

LarsErik


2 Answers

The precise rules governing forward reference to class variables are described in the section §8.3.2.3 of the JLS:

8.3.2.3 Restrictions on the use of Fields during Initialization

The declaration of a member needs to appear textually before it is used only if the member is an instance (respectively static) field of a class or interface C and all of the following conditions hold:

  • The usage occurs in an instance (respectively static) variable initializer of C or in an instance (respectively static) initializer of C.
  • The usage is not on the left hand side of an assignment.
  • The usage is via a simple name.
  • C is the innermost class or interface enclosing the usage.

A compile-time error occurs if any of the four requirements above are not met.

This means that a compile-time error results from the test program:

  class Test {
      int i = j;  // compile-time error: incorrect forward reference
      int j = 1;
  }

whereas the following example compiles without error:

  class Test {
      Test() { k = 2; }
      int j = 1;
      int i = j;
      int k;
  }

even though the constructor (§8.8) for Test refers to the field k that is declared three lines later.

These restrictions are designed to catch, at compile time, circular or otherwise malformed initializations. Thus, both:

class Z {
  static int i = j + 2; 
  static int j = 4;
}

and:

class Z {
  static { i = j + 2; }
  static int i, j;
  static { j = 4; }
}

result in compile-time errors. Accesses by methods are not checked in this way, so:

class Z {
  static int peek() { return j; }
  static int i = peek();
  static int j = 1;
}
class Test {
  public static void main(String[] args) {
      System.out.println(Z.i);
  }
}

produces the output:

0

because the variable initializer for i uses the class method peek to access the value of the variable j before j has been initialized by its variable initializer, at which point it still has its default value (§4.12.5).

like image 121
Pascal Thivent Avatar answered Sep 30 '22 17:09

Pascal Thivent


I would assume that by using the class, the compiler would defer looking for the variable until the class was complete, so it finds y, but if you just define it like the comment it is not yet defined so it fails

like image 32
Woody Avatar answered Sep 30 '22 19:09

Woody