3

I've checked Forward References During Field Initialization and this the answer from @assylias, but still I got no answer to the why.

Why a static block can assign the static variable declared after it but can NOT access it?

   class Parent {
        static {
            i = 2; // valid
            // can only assign new value to it instead of accessing it?
//            System.out.println(i); // invalid - compile-error
        }
        static int i = 0;
        static {
            i = 3; // valid
        }
    }

Is it due to the fact: the value is not initialized yet, so we just explicitly inhibit you from using it? or there are something related to security I don't know?


updated

this is not a duplicate of that problem which is about

Why this doesn't happen when accessing with class name?

This question is about why we have this design? for what purpose?

8
  • there will be compile error as mentioned @Lino so you simply cannot get the bytecode Commented Mar 19, 2019 at 6:55
  • 2
    @Lino This code doesn't compile. There is no bytecode to check. Don't post meaningless guesswork here. Commented Mar 19, 2019 at 6:56
  • Yes, it is because it isn't initialized yet, which is what the error message says, isn't it? Commented Mar 19, 2019 at 6:58
  • 1
    Possible duplicate of Why illegal forward reference error not shown while using static variable with class name Commented Mar 19, 2019 at 7:02
  • 2
    @Hearen Asking why language desicions were made are not easy-to-answer-questions. This requires quite in-depth knowledge from one of the java developers and unless Brian Goetz comes around I am not sure if anyone here can answer this Commented Mar 19, 2019 at 7:10

3 Answers 3

4

Static fields are initialized based on the order they appear in the code.

So, when you assign a value to i variable you just say to the compiler: "Hey, guy, when you get to initialize this variable, set its value to...". But you can not use it until it's initialized because it simply does not exist yet.

UPDATE:

As it says in the book "The Java Language Specification" by James Gosling, Bill Joy, Guy Steele and Gilad Bracha:

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

Consider this:

static {
            i = 2;
            j = i + 5; //should it be 7 or 15?
}
static int i = 10;
static int j;

Should j variable be 7 or 15? If it's 7, then we have initialized i variable twice, which is not possible, since the field is static. If it's 15 then what does i = 2; mean?

This code is ambiguous, so Java Specification does not allow to do that.

Sign up to request clarification or add additional context in comments.

4 Comments

Provided some explanation.
Wow, thank you so much. I just got lost and have no idea why this is not allowed. This example does give me the clue. Thank you so much! Pavel
then we have initialized i variable twice, which is not possible, since the field is static” ahem, why do you think that this is not possible? You can assign a variable as often as you like, unless it is final. You can easily write static int i = 2, j = i++ + 5; static { i += 3; } Or you change j = i + 5; in your own example to j = ClassName.i + 5; and it works, as the variable does exist already.
It says so in Java specification: "At run time, the initializer is evaluated and the assignment performed exactly once, when the class is initialized". Here docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.3 and here docs.oracle.com/javase/specs/jls/se8/html/… About referencing a variable by its full name. In this case the compiler knows exactly that the class has already been initialized This question was discussed here: stackoverflow.com/questions/29153703/…
0

After some further reading, I think Pavel is not quite accurate in this point as @Holger pointed out in the comment.

we have initialized i variable twice, which is not possible, since the field is static.

As the 12.4.2. Detailed Initialization Procedure points out

For each class or interface C, there is a unique initialization lock LC. The mapping from C to LC is left to the discretion of the Java Virtual Machine implementation.

I suppose the initialization twice is okay to the class initializer itself as long as it's just once to the invoking clients.

But the demos Pavel provided still stands its position so I basically just reuse it here but with different explanation.

static {
       i = 2;
       j = i + 5; 
       // no one knows whether "i" here initialized properly here
}
static int i = 10;
static int j;

But when you use MyClass.i directly in j = MyClass.i + 5, the compiler would know it would then be okay as 8.3.3. Forward References During Field Initialization detailed with four conditions.

Specifically, it is a compile-time error if all of the following are true:

  1. The declaration of a class variable in a class or interface C appears textually after a use of the class variable;

  2. The use is a simple name in either a class variable initializer of C or a static initializer of C;

  3. The use is not on the left hand side of an assignment;

  4. C is the innermost class or interface enclosing the use.

And there is a detailed discussion in this answer already.

To wind it up, I think this would be for predictable behavior to add these restrictions. Once again, the other official purpose pointed out in 8.3.3. Forward References During Field Initialization.

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

Comments

0

The same is also applicable to the non-static members. You can assign values to them in instance initializer block but can not use them before initialization.

class Parent {
    {
        x = 3; // works fine
        // System.out.println(x); // gives compilation error.

    }
    int x = 0;

    public static void main(String[] args) {

    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.