Unravel โบ Java concepts โบ Language basics
Initialisation order and init blocks
A static { ...
Learn these first
At a glance
Opening a restaurant: the building is set up once (static block), and each new table gets its cutlery before the guests sit down (instance block, then constructor).
- 1Order for one class: static fields and static blocks (top to bottom) once; then for every new: parent constructor, instance fields and instance blocks (top to bottom), then the rest of the constructor
- 2A static block is the place to fill a static map or to load a native library: static { LOOKUP.put("a", 1); }
- 3An instance initialiser block is rarely needed; it is mostly seen in anonymous classes ("double brace initialisation")
- An exception thrown in a static block becomes ExceptionInInitializerError, and afterwards the class is unusable (NoClassDefFoundError on every later use)
- Static initialisation is thread safe: the JVM locks the class while it runs
- The compiler gathers all static initialisers into a synthetic method <clinit> that the JVM runs once at class initialisation, and all instance initialisers into the start of each <init> constructor
public class Codes { private static final java.util.Map<String, Integer> LOOKUP = new java.util.HashMap<>(); static { LOOKUP.put("ok", 200); LOOKUP.put("missing", 404); } private final long created; { created = System.nanoTime(); }}Read the full explanation (about 1 min)
A static { ... } block runs once when the class is first used; a plain { ... } block runs before every constructor. They run in a strict order together with field initialisers.
A mental model
Opening a restaurant: the building is set up once (static block), and each new table gets its cutlery before the guests sit down (instance block, then constructor).
How it works
Order for one class: static fields and static blocks (top to bottom) once; then for every new: parent constructor, instance fields and instance blocks (top to bottom), then the rest of the constructor.
A static block is the place to fill a static map or to load a native library: static { LOOKUP.put("a", 1); }.
An instance initialiser block is rarely needed; it is mostly seen in anonymous classes ("double brace initialisation").
Going deeper
An exception thrown in a static block becomes ExceptionInInitializerError, and afterwards the class is unusable (NoClassDefFoundError on every later use). Keep static blocks small and safe.
Static initialisation is thread safe: the JVM locks the class while it runs. Circular dependencies between two classes' static blocks can deadlock.
Under the hood
The compiler gathers all static initialisers into a synthetic method <clinit> that the JVM runs once at class initialisation, and all instance initialisers into the start of each <init> constructor.
Common mistakes
- Relying on a static field of another class being initialised already.
- Throwing from a static block.
- Double brace initialisation (
new ArrayList<>() {{ add(1); }}) which creates an extra anonymous class per use and leaks the outer object.
How Unravel recognises it
When you paste code, Unravel looks for these signs of initialisation order and init blocks. Spotting them yourself is a good habit when you read unfamiliar code:
- Language constructs:
static-initinit-block
Part of a learning path
- Object-oriented Java in depth ยท previous: static and final members ยท next: Immutability and final classes
Related concepts
Frequently asked questions
What is Initialisation order and init blocks?
A static { ... } block runs once when the class is first used; a plain { ... } block runs before every constructor. They run in a strict order together with field initialisers.
What are the most common mistakes with Initialisation order and init blocks?
Relying on a static field of another class being initialised already. Throwing from a static block. Double brace initialisation (new ArrayList<>() {{ add(1); }}) which creates an extra anonymous class per use and leaks the outer object.
How can I see Initialisation order and init blocks in real code?
Paste your own Java into Unravel and it will point out where initialisation order and init blocks appears, explain how it works at the detail level you choose, and draw the flow of the code around it.