library
intermediateInitialization Blocks: Static & Instance
Understand the order of execution of static blocks, instance blocks, constructors, and field initializers.
An initialization block is code in braces that runs automatically — not inside any method.
Static block = setting up the factory before any product is made (happens once). Instance block = quality check on the assembly line (happens for every product before it ships).
Key Concepts
1
class Example {
static { System.out.println("static block"); } // once, ever
{ System.out.println("instance block"); } // every new object
Example() { System.out.println("constructor"); }
}2
A static block runs once, the first time the class is used. An instance block runs every time you create
an object, just before the constructor body.
static
3
The order, for new Child() where Child extends Parent.
1. Parent's static fields and static blocks once, ever
2. Child's static fields and static blocks once, ever
3. Parent's instance fields and blocks every object
4. Parent's constructor body
5. Child's instance fields and blocks
6. Child's constructor bodynew Child()
4
Static before instance. Parent before child. That is the whole rule.
5
"The first time the class is used" is more precise than it sounds. Creating an object counts. Calling a
static method counts. Reading a normal static field counts.
6
Reading a static final constant does not, because the compiler copies the value into your code and
the class is never touched.
static final
7
The bug this causes. Step 4 runs before step 5. So if a parent constructor calls a method the child has
overridden, the child's version runs before the child's fields exist:
8
class Parent {
Parent() { init(); } // calls the child's version
void init() { }
}
class Child extends Parent {
private String name = "set"; // assigned at step 5
@Override void init() {
System.out.println(name); // prints null
}
}9
The object is real enough to call methods and not yet real enough to answer them. This is why you never
call an overridable method from a constructor.
10
A failing static block poisons the class permanently. If a static block throws, you get
ExceptionInInitializerError once. Every later attempt to use that class throws NoClassDefFoundError
with no explanation of the original cause.
ExceptionInInitializerErrorNoClassDefFoundError
11
In a long-running service, only the first failure in the log is useful and everything after it is
misleading. Keep static blocks trivial, and put anything that can fail behind an initialisation method you
call deliberately.
12
What the interviewer is probing.1. "What order do these run in?" Probing: precision. Stalls: "Constructor first." Moves up: the
six steps, static before instance, parent before child.
13
2. "When does a static block run?" Probing: what triggers it. Stalls: "When the class loads."
Moves up: loading and initialising are different; it runs on first real use, and a compile-time constant
does not count.
14
3. "Why not call an overridable method from a constructor?" Probing: the real bug. Stalls: "Bad
practice." Moves up: the override runs before the subclass fields are assigned, so it sees nulls.
15
4. "A static block throws. What happens?" Probing: failure behaviour. Stalls: "An exception."
Moves up: one ExceptionInInitializerError, then NoClassDefFoundError forever.
ExceptionInInitializerErrorNoClassDefFoundError
16
5. "Instance block or constructor?" Probing: judgement. Stalls: "They are the same." Moves up:
blocks share setup between several constructors, but a private method is usually clearer.
17
Order for `new Child()` where Child extends Parentnew Child()
18
1 Parent static fields + static blocks once, in source order
2 Child static fields + static blocks once, in source order
3 Parent instance fields + instance blocks every construction
4 Parent constructor body
5 Child instance fields + instance blocks
6 Child constructor body19
What triggers step 1/2 (class initialisation)
new Child() yes
Child.staticMethod() yes
Child.NON_CONSTANT_FIELD yes
Child.COMPILE_TIME_CONSTANT (static final
int = 42) NO - inlined
Class.forName("Child") yes
Child.class literal no20
The constructor trap21
class Parent {
Parent() { init(); } // calls the override
void init() { }
}
class Child extends Parent {
private String name = "set"; // runs AFTER Parent()
@Override void init() {
System.out.println(name); // prints null
}
}