In what order do static/instance initializer blocks in Java run?
Say a project contains several classes, each of which has a static initializer block. In what order do those blocks run? I know that within a class, such blocks are run in the order they appear in the code. I've read that it's the same across classes, but some sample code I wrote disagrees with that. I used this code:
package pkg;
public class LoadTest {
public static void main(String[] args) {
System.out.println("START");
new Child();
System.out.println("END");
}
}
class Parent extends Grandparent {
// Instance init block
{
System.out.println("instance - parent");
}
// Constructor
public Parent() {
System.out.println("constructor - parent");
}
// Static init block
static {
System.out.println("static - parent");
}
}
class Grandparent {
// Static init block
static {
System.out.println("static - grandparent");
}
// Instance init block
{
System.out.println("instance - grandparent");
}
// Constructor
public Grandparent() {
System.out.println("constructor - grandparent");
}
}
class Child extends Parent {
// Constructor
public Child() {
System.out.println("constructor - child");
}
// Static init block
static {
System.out.println("static - child");
}
// Instance init block
{
System.out.println("instance - child");
}
}
and got this output:
START
static - grandparent
static - parent
static - child
instance - grandparent
constructor - grandparent
instance - parent
constructor - parent
instance - child
constructor - child
END
The obvious answer from that is that parents' blocks run before their children's, but that could just be a coincidence and doesn't help if two classes aren't in the same hierarchy.
EDIT:
I modified my example code by appending this to LoadTest.java:
class IAmAClassThatIsNeverUsed {
// Constructor
public IAmAClassThatIsNeverUsed() {
System.out.println("constructor - IAACTINU");
}
// Instance init block
{
System.out.println("instance - IAACTINU");
}
// Static init block
static {
System.out.println("static - IAACTINU");
}
}
As implied by the class name, I never referenced the new class anywhere. The new program produced the same output as the old one.
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.
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:
(and several weasel-word clauses)
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:
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:
上一篇: Java中的静态初始化器