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
You can have multiple static and instance initializers in the same class, therefore
Each is executed as if it was a single block.
There is one case in which a static block will not be called.
class Super {
public static int i=10;
}
class Sub extends Super {
static {
system.out.println("Static block called");
}
}
class Test {
public static void main (String [] args) {
system.out.println(Sub.i);
}
}
The above code outputs 10
Update from an "editor"
The technical explanation for this is in JLS 12.4.1
"A reference to a static field (§8.3.1.1) causes initialization of only the class or interface that actually declares it, even though it might be referred to through the name of a subclass, a subinterface, or a class that implements an interface."
The intuitive explanation is Super.i
and Sub.i
are actually the same variable, and nothing in Sub
actually needs to be initialized for the Super.i
to get the correct value.
(It would be different if the initialization expression for Super.i
referred to the Sub
class. But then you would have a cycle in the initialization order. A careful reading of JLS 12.4.1 and JLS 12.4.2 explains that this is allowed, and allows you to work out exactly what would happen in practice.)
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:
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.
class A {
public A() {
// 2
}
}
class B extends A{
static char x = 'x'; // 0
char y = 'y'; // 3
public B() {
// 4
}
public static void main(String[] args) {
new B(); // 1
}
}
Numbers in the comment indicate the evaluation order, the smaller, the earlier.
As the example showed,
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)