jarek
jarek

Reputation: 61

Why can I assign to a variable declared after the initalizer, but not print it?

I'm plaing with the initialization order and cannot explain why line 7 is compiled b = 3; but the next line 8 System.out.println("b: " + b); isn't. Can somebody explain this and fill up this knowledge gap?

Without line 8 the code compiles well and print "2 4".

public class InitializationOrder {

    Integer a = 1;

    {
        a = 2;
        b = 3;
        System.out.println("b: " + b); // DOES NOT COMPILE
// InitializationOrder.java:8: error: illegal forward reference
//         System.out.println("b: " + b);
//                                    ^
// 1 error
// error: compilation failed
    }

    Integer b = 4;

    public InitializationOrder() {
        System.out.println(a + " " + b); // 2 4 - when line 8 is commented
    }

    public static void main(String[] args) {
        InitializationOrder obj = new InitializationOrder();
    }
}

Upvotes: 3

Views: 87

Answers (2)

M A
M A

Reputation: 72864

This is part of the restrictions on field references in initializers as documented by the Java Language Specification:

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 an instance variable f declared in class C, it is a compile-time error if:

  • The reference appears either in an instance variable initializer of C or in an instance initializer of C (§8.6); and
  • The reference appears in the initializer of f's own declarator or at a point to the left of f's declarator; and
  • The reference is not on the left hand side of an assignment expression (§15.26); and
  • The innermost class enclosing the reference is C.

The JLS describes why these restrictions apply:

The restrictions above are designed to catch, at compile time, circular or otherwise malformed initializations.

So basically to avoid scenarios like:

class Test {
    int i = j;
    int j = i;
}

(even though in your case printing the field may not be a dangerous thing to do)

Upvotes: 4

Benjamin M
Benjamin M

Reputation: 24527

In Eclipse I get a better Error message:

Cannot reference a field before it is defined

Now it should be pretty obvious why you get the error.

Upvotes: 0

Related Questions