I'm trying to discover the order in which initialization occurs, or rather the reason behind why initialization occurs in this order. Given the code:
public class Main {
{
System.out.printf("NON-STATIC BLOCK\n");
}
static{
System.out.printf("STATIC BLOCK\n");
}
public static Main m = new Main();
public Main(){
System.out.printf("MAIN CONSTRUCTOR\n");
}
public static void main(String... args) {
//Main m = new Main();
System.out.printf("MAIN METHOD\n");
}
}
Output:
STATIC BLOCK
NON-STATIC BLOCK
MAIN CONSTRUCTOR
MAIN METHOD
However, moving m
's declaration before the initialization block produces:
NON-STATIC BLOCK
MAIN CONSTRUCTOR
STATIC BLOCK
MAIN METHOD
and I have absolutely no idea why it occurs in this order. Furthermore, if I eliminate the static
keyword in the declaration of m
, neither the init block nor the constructor fire. Can anyone help me out with this?
I think you're just missing section 12.4.2 of the JLS, which includes:
Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
The "in textual order" part is the important bit.
If you change m
from being static variable to an instance variable, then the field won't be initialized by class initialization - it'll only be initialized by instance initialization (i.e. when an instance is constructed). At the moment, that'll cause a stack overflow - creating one instance requires creating another instance, which requires creating another instance, etc.
EDIT: Similarly section 12.5 specifies instance initialization, including these steps:
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.
So that's why you're seeing "NON-STATIC BLOCK" before "MAIN CONSTRUCTOR".
See more on this question at Stackoverflow