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:
The declaration of a class variable in a class or interface C appears
textually after a use of the class variable;
The use is a simple name in either a class variable initializer of C
or a static initializer of C;
The use is not on the left hand side of an assignment;
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.