What is the difference between static and instance initializer blocks, and what order do they run in?

8 minintermediateinitializer-blocksclass-loading

Quick Answer

A static block runs once when the class is first loaded, before any instance exists. An instance initializer block runs every time a new object is constructed, right before the constructor body, after the superclass constructor has run. Order overall: static blocks/fields (in source order, once) -> instance blocks/fields -> constructor body, each time an object is created.

Detailed Answer

Java has two kinds of initializer blocks, run at different times:

  • Static initializer block (static { ... }): runs exactly once, when the class is first loaded/initialized by the JVM — before any instance is created and before main() even, if that class contains it.
  • Instance initializer block ({ ... }, no static): runs every time a new instance is constructed, right after the superclass constructor completes and before the current class's constructor body executes.

Full order when creating an object of a subclass for the first time:

  1. Superclass static blocks/fields (in source order) — once, on first load.
  2. Subclass static blocks/fields (in source order) — once, on first load.
  3. For each new call: superclass constructor runs (which itself runs superclass instance blocks, then its constructor body) → subclass instance blocks/field initializers (in source order) → subclass constructor body.
class Base {
    static { System.out.println("Base static"); }
    { System.out.println("Base instance"); }
    Base() { System.out.println("Base ctor"); }
}
class Derived extends Base {
    static { System.out.println("Derived static"); }
    { System.out.println("Derived instance"); }
    Derived() { System.out.println("Derived ctor"); }
}
new Derived();
// Base static, Derived static, Base instance, Base ctor, Derived instance, Derived ctor

Static blocks are useful for one-time setup (loading config, registering drivers); instance blocks are less common than field initializers but useful for logic that field initializers can't express (e.g., a switch during setup) shared by every constructor.