Why Does Java Initialize Static Members Before Instance Members? A Deep Dive into Object Initialization
The article explains Java's two‑phase object initialization, the seven‑step JVM process, static versus instance execution order, parent‑child class initialization rules, variable assignment lifecycle, and common pitfalls such as static forward references and constructor‑called overridden methods, all illustrated with concrete code examples.
Two phases of Java object initialization
Phase 1 – class (static) initialization runs once per class, independent of any object. It initializes static fields and executes static blocks. The JVM merges all static code into a single <clinit> method.
Phase 2 – instance initialization runs on each new. It initializes instance fields, executes instance blocks, and finally runs the constructor. The JVM merges all instance code into a single <init> method.
JVM standard 7‑step initialization process for a single class
Class loading – load, verify, prepare, resolve.
Static fields receive default values (0, null, false).
Explicit static field assignments and static blocks execute top‑down.
Memory for the new object is allocated; instance fields receive default values.
Explicit instance field assignments and instance blocks execute top‑down.
Constructor body executes.
Object reference is returned; the instance is fully created.
Demonstration of single‑class initialization
public class Demo {
static int a = print("static variable");
int b = print2("instance variable");
static { print("static block"); }
{ print2("instance block"); }
public Demo() { print2("constructor"); }
public static int print(String s) { System.out.println(s); return 1; }
public int print2(String s) { System.out.println(s); return 1; }
public static void main(String[] args) { new Demo(); }
}Standard output:
static variable
static block
instance variable
instance block
constructorParent‑child class initialization order
The execution order is:
Parent static fields and static blocks.
Child static fields and static blocks.
Parent instance fields, instance blocks, then parent constructor.
Child instance fields, instance blocks, then child constructor.
class Father {
static { System.out.println("parent static block"); }
{ System.out.println("parent instance block"); }
public Father() { System.out.println("parent constructor"); }
}
class Son extends Father {
static { System.out.println("child static block"); }
{ System.out.println("child instance block"); }
public Son() { System.out.println("child constructor"); }
public static void main(String[] args) { new Son(); }
}Output:
parent static block
child static block
parent instance block
parent constructor
child instance block
child constructorVariable assignment lifecycle (four layers)
Every Java variable is assigned in four successive steps, each later step overriding the previous one:
Default initialization by the JVM (0, null, false).
Explicit field initializer (e.g., int a = 10;).
Instance block assignment (e.g., { a = 20; }).
Constructor assignment (final override).
public class Test {
int a = 10;
{ a = 20; }
public Test() { a = 30; }
public static void main(String[] args) {
System.out.println(new Test().a); // prints 30
}
}Common pitfalls
1. Parent constructor calls an overridden method
class Father {
public Father() { show(); }
public void show() {}
}
class Son extends Father {
int x = 100;
@Override public void show() { System.out.println(x); } // prints 0
}Reason: the parent constructor runs before the child’s instance fields are initialized, so the overridden method sees the default value.
2. Illegal forward reference in a static context
static { System.out.println(num); } // compile‑time error
static int num = 10;Static code is executed top‑down; a static variable cannot be accessed before its declaration. Access via a method is allowed.
3. Static methods are not polymorphic
Static methods belong to the class, are bound at compile time, and cannot be overridden.
4. Private methods are not inherited
Therefore they cannot be overridden.
5. Final methods cannot be overridden
Attempting to do so results in a compile‑time error.
6. Subclass cannot narrow access modifiers or broaden checked exceptions
Overriding must keep the method at least as accessible and cannot add new checked exceptions.
7. Interface constants ( static final ) do not trigger class initialization
Accessing a compile‑time constant does not cause the declaring interface to be initialized.
Static vs. instance comparison
Execution timing : static – class loading phase; instance – during new.
Execution count : static – once per JVM; instance – once per object creation.
Ownership : static – class; instance – object.
Inheritance rule : static – parent static before child static; instance – parent instance before child instance.
Class initialization triggers
Creating a new object ( new).
Accessing a static method or static field.
Initializing a subclass (which also initializes its superclass).
Reflective call Class.forName().
Running the main class.
Operations that do NOT trigger initialization
Accessing a static final compile‑time constant.
Declaring a reference variable without creating an instance.
JVM internal mechanisms
<clinit> – static initialization method
The compiler automatically merges all static field initializers and static blocks into a single synthetic method <clinit>. Characteristics:
Automatically synchronized – thread‑safe.
Executed only once.
No parameters; invoked by the JVM during class loading.
<init> – instance initialization method
The compiler merges all instance field initializers, instance blocks, and constructor body into a synthetic method <init>. Characteristics:
Executes for each object creation.
Contains explicit field assignments, instance block code, and constructor statements.
Super constructor rule
In a subclass constructor, the first statement is an implicit call to super(). Consequently, the superclass’s static initialization (if not already done) and instance initialization run before any subclass instance fields are assigned.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Tech Workshop
Focused on Java backend technologies, sharing fundamentals, multithreading, JVM, the Spring ecosystem, microservices, distributed systems, high concurrency, source‑code analysis, and practical experience. Continuously delivers high‑quality original content, interview guides, and learning roadmaps to help Java developers progress from beginner to advanced, enhancing technical skills and core competitiveness.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
