skip to content

In what order are static variables, instance variables, and their initializer blocks set up when a class is first used and an object is created?

level: seniorimportance: nice to knowfreq 35%

answer

  1. Static = once, on first use, top to bottom
  2. Instance = every new: defaults → super → field/blocks → ctor body
  3. Parent fully initialized before child field initializers
  4. Don't call overridable methods from a constructor
  5. Initializer blocks run in textual order

basics

~20 s

Static parts run once when the class is first loaded, top to bottom. Then, every time you create an object, the instance fields and instance blocks run top to bottom, and finally the constructor body runs.

solid answer

~40 s

Initialization happens in two phases. Class initialization runs once, the first time the class is actively used: the JVM assigns default values, then runs static field initializers and static initializer blocks in textual order. Object initialization runs on every new: defaults are assigned to the instance fields, the superclass constructor runs first (explicit or implicit super()), then instance field initializers and instance initializer blocks run in textual order, and finally the rest of the constructor body executes. So statics never re-run per object, the parent is fully initialized before the child's field initializers, and you can see surprising results if a constructor calls an overridden method before the subclass fields are initialized. Knowing this order explains NullPointerExceptions during construction and why forward references to fields not yet initialized are restricted.

go deeper

for a junior

State the basic idea: static setup happens once when the class loads; instance fields and the constructor run each time you create an object.

for a middle

Lay out the full per-object order (defaults, super, field initializers/blocks, constructor) and that statics run once.

for a senior

Explain the consequences: the constructor-calls-overridable-method trap, forward-reference rules, and resulting NPEs.

for a principal

Use this to set design rules (no overridable calls in constructors, prefer immutable/final fields, factory methods) and reason about class-loading order in larger systems.

## Two separate phases Java sets up a class in two distinct phases: **class (static) initialization**, which happens *once*, and **instance initialization**, which happens on *every* object creation. ### Phase A — Class initialization (once per class) This is triggered the first time the class is **actively used** — e.g. the first `new`, the first access to a static member, or `Class.forName`. The JVM: 1. Loads and links the class, giving every static field its **default value** (0/false/null). 2. Runs all **static field initializers** and **static initializer blocks** (`static { ... }`) **in the order they appear** in the source. This happens *only once* for the lifetime of the class; statics are never re-initialized per object. ```java static int a = 1; // (1) static { a = a + 10; } // (2) runs after (1): a becomes 11 ``` ### Phase B — Instance initialization (every `new`) When you write `new T()`: 1. Memory for the object is allocated and all **instance fields get default values**. 2. The **superclass** is initialized first: the constructor begins with an explicit or implicit `super(...)` call, which fully runs the parent's instance initialization before returning. 3. Then this class's **instance field initializers** and **instance initializer blocks** (`{ ... }` with no `static`) run **in textual order**. 4. Finally, the **rest of the constructor body** runs. So the effective per-object order is: *defaults → super() → field initializers + instance blocks (top to bottom) → constructor body.* ```java class Parent { Parent() { System.out.println("parent ctor"); } } class Child extends Parent { int x = init("field x"); // runs after super(), before ctor body { System.out.println("instance block"); } Child() { System.out.println("child ctor"); } static int init(String s){ System.out.println(s); return 0; } } // new Child() prints: parent ctor, field x, instance block, child ctor ``` ### Why the order matters in practice **1. The 'overridable method in constructor' trap.** Because the parent constructor runs *before* the child's field initializers, if the parent constructor calls a method that the child overrides, the override runs while the child's fields are still at their defaults (e.g. `null`/`0`): ```java class Base { Base(){ render(); } void render(){} } class Sub extends Base { String name = "set"; @Override void render(){ System.out.println(name.length()); } // NPE: name is still null } ``` This is why a constructor should not call overridable methods. **2. Forward-reference restrictions.** A field initializer cannot read a later field via its simple name before that field is initialized; the compiler restricts illegal forward references to avoid reading defaults unexpectedly. **3. Static vs instance is independent.** Class initialization is fully done before any instance initialization that triggers it, but statics are not part of per-object setup. ### Quick reference - **Once, on first active use:** static field initializers + static blocks, in source order. - **Every new:** defaults → `super(...)` → instance field initializers + instance blocks (source order) → constructor body.

  • Why can calling an overridable method from a constructor cause a NullPointerException?
    The superclass constructor runs before the subclass's field initializers. If it calls an overridden method, that method sees the subclass fields still at their defaults (null/0), so dereferencing them throws.
  • Do static initializer blocks run every time you create an object?
    No. Static initialization runs only once, when the class is first actively used. Object creation only triggers instance initialization.

saying these in an interview costs you the question

  • Thinking static initializers re-run for each object
  • Assuming the constructor body runs before field initializers
  • Believing child fields are set before the parent constructor finishes
  • Calling an overridable method in a constructor and expecting child fields to be ready

context