In what order do static/instance initializer blocks in Java run?
Solution 1:
See section 12.4 and 12.5 of the JLS version 8, they go into gory detail about all of this (12.4 for static and 12.5 for instance variables).
For static initialization (section 12.4):
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
- T is a class and an instance of T is created.
- T is a class and a static method declared by T is invoked.
- A static field declared by T is assigned.
- A static field declared by T is used and the field is not a constant variable (§4.12.4).
- T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
(and several weasel-word clauses)
Solution 2:
The static initializer for a class gets run when the class is first accessed, either to create an instance, or to access a static method or field.
So, for multiple classes, this totally depends on the code that's run to cause those classes to get loaded.
Solution 3:
Keith's and Chris's answers are both great, I'm just adding some more detail for my specific question.
Static init blocks run in the order in which their classes are initialized. So, what order is that? Per JLS 12.4.1:
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
- T is a class and an instance of T is created.
- T is a class and a static method declared by T is invoked.
- A static field declared by T is assigned.
- A static field declared by T is used and the field is not a constant variable (§4.12.4).
- T is a top-level class, and an assert statement (§14.10) lexically nested within T is executed.
Invocation of certain reflective methods in class Class and in package java.lang.reflect also causes class or interface initialization. A class or interface will not be initialized under any other circumstance.
To illustrate, here's a walkthrough of what's happening in the example:
- Enter main
- Print "START"
- Attempt to create first instance of Child, which requires initialization of Child
- Attempting to initialize Child causes initialization of Parent
- Attempting to initialize Parent causes initialization of Grandparent
- At the start of initialization of Grandparent, Grandparent's static initialization block is run
- Technically, Object gets the last say in the initialization chain by virtue of being Grandparent's parent, but it has nothing to contribute
- After Grandparent's static initialization block ends, program falls back to Parent's static initialization block
- After Parent's static initialization block ends, program falls back to Child's static initialization block
- At this point, Child is initialized, so its constructor may proceed
- Since IAmAClassThatIsNeverUsed never gets referenced, none of its code ever runs, including static initializer blocks
- The rest of this walkthrough doesn't concern static initializers and is included only for completeness
- Child's constructor implicitly calls super() (i.e., Parent's constructor)
- Parent's constructor implicitly calls super() (i.e., Grandparent's constructor)
- Grandparent's constructor does the same, which has no effect (again, Object has nothing to contribute)
- Immediately after Grandparent's constructor's call to super() comes Grandparent's instance initializer block
- The rest of Grandparent's constructor's constructor runs and the constructor terminates
- The program falls back to Parent's constructor, immediately after its call to super() (i.e., Grandparent's constructor) resolves
- As above, Parent's instance initializer does its thing and its constructor finishes up
- Similarly, the program returns to and completes Child's constructor
- At this point, the object has been instantiated
- Print "END"
- Terminate normally
Solution 4:
Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class.
Initialization of an interface consists of executing the initializers for fields (constants) declared in the interface.
Before a class is initialized, its direct superclass must be initialized, but interfaces implemented by the class are not initialized. Similarly, the superinterfaces of an interface are not initialized before the interface is initialized.