🏗️ Classes & Objects · Intermediate

Initializer blocks & init order in Java

Static blocks once at class init; instance blocks before the constructor body.

🧩 The mysteryYou put a print in a constructor, a static { } block and a plain { } block, then create two objects. Most people guess the order wrong the first time. Will you?

Two kinds of setup

Class setup happens once; object setup happens on every new. A static { } block is class setup: it runs once, when the class is first initialized.

class Demo {
    static { System.out.print("S"); }
}

Instance blocks

A plain { } block in a class body is an instance initializer. It runs on **every new, together with field initializers in source order, and all of them run before the constructor body**.

class Demo {
    { System.out.print("I"); }
    Demo() { System.out.print("C"); }
}
// new Demo() prints IC
🔮 Predict it

Open the gate twice

What does this print?

class Gate {
    static { System.out.print("1"); }
    { System.out.print("2"); }
    Gate() { System.out.print("3"); }
}
void main() {
    new Gate();
    new Gate();
}
  1. 123123
  2. 12323
  3. 23123
  4. 1323
Show the answer

12323. The static block prints 1 once, when Gate is initialized. Each new then runs the instance block (2) before the constructor body (3).

Source order wins

Field initializers and instance blocks are merged top to bottom, then the constructor body runs last. Here the order is a, block, b, ctor.

class Order {
    int a = log("a");
    { log("block"); }
    int b = log("b");
    Order() { log("ctor"); }
}
🔮 Predict it

When does the class wake up?

Classes are initialized lazily, on first active use. What prints?

class Cfg {
    static { System.out.print("load "); }
    static int port = 80;
}
void main() {
    System.out.print("go ");
    System.out.print(Cfg.port);
}
  1. load go 80
  2. go load 80
  3. go 80
Show the answer

go load 80. Cfg isn't touched until Cfg.port is read — a non-constant static field — which triggers its static block right then.

⚠️ The trap

Constants don't wake the class

A static final field with a compile-time constant value is copied into the caller by the compiler. Reading it does not initialize the class — so the static block below never runs: this prints just 7.

class K {
    static { System.out.print("init "); }
    static final int X = 7; // constant
}
// System.out.print(K.X);  ->  7
💼 In the real world

In real projects

Static blocks load configuration, build lookup tables and load native libraries (static { System.loadLibrary("x"); } is a common JNI pattern). Old JDBC drivers registered themselves in a static block — that's why code used to call Class.forName("...Driver").

Key takeaways

  1. static { } runs once per class, at first active use
  2. Instance initializers and { } blocks run in source order
  3. They run before the constructor body, on every new
  4. Reading a non-constant static field triggers class init
🤯 Did you know?

If a static initializer throws, the class becomes unusable: the first use fails with ExceptionInInitializerError, and every later use with NoClassDefFoundError.

Practice questions

What does this print?

class Demo {
    static { System.out.print("S"); }
    { System.out.print("I"); }
    Demo() { System.out.print("C"); }
}
void main() {
    new Demo();
    new Demo();
}
  1. SICSIC
  2. SICIC
  3. ICSIC
  4. SCICI
Check your answer

SICIC. S prints once when Demo is initialized. Each new then runs the instance block (I) before the constructor body (C).

What does this print?

class Order {
    int a = log("a");
    { log("block"); }
    int b = log("b");
    Order() { log("ctor"); }
    static int log(String s) {
        System.out.print(s + " "); return 0;
    }
}
void main() { new Order(); }
  1. a b block ctor
  2. a block b ctor
  3. block a b ctor
  4. ctor a block b
Check your answer

a block b ctor. Field initializers and instance blocks are merged in source order (a, block, b) and run before the constructor body.

Next: two variables, one object — and the null that brought it all down.