Java类初始化顺序固定为:先静态后普通、先父类后子类;类加载阶段执行父类静态变量/块→子类静态变量/块,对象实例化阶段执行父类普通代码块与成员变量初始化→父类构造器→子类普通代码块与成员变量初始化→子类构造器。

类加载阶段:静态内容只跑一次,父类先于子类
当程序第一次用到某个类(比如 new Son()),JVM会先确保父类已加载并初始化,再处理子类:
- 父类的静态变量(按声明顺序)→ 父类静态代码块(按书写顺序)
- 子类的静态变量(按声明顺序)→ 子类静态代码块(按书写顺序)
这个阶段不涉及成员变量(非静态),也不创建对象,只做“类准备”。静态内容全程只执行一次,后续 new 多少次都不重复。
对象实例化阶段:每次 new 都走一遍,父类初始化完才轮到子类
执行 new Son() 时,JVM为对象分配内存后,按以下固定顺序填充实例:
- 父类非静态字段设默认值(如 int→0,Object→null)
- 父类普通代码块(即 {} 块)→ 同时执行父类成员变量显式初始化(如 String name = "Alice"; 被编译器自动“挪”进这里)
- 父类构造方法(含隐式或显式 super())
- 子类非静态字段设默认值
- 子类普通代码块 → 同时执行子类成员变量显式初始化
- 子类构造方法体
注意:成员变量的初始化语句(如 int x = 5;)和普通代码块地位相同,都被编译器插入到对应类每个构造方法开头、super()调用之后的位置,所以一定在构造方法逻辑之前运行。
立即学习“Java免费学习笔记(深入)”;
为什么必须这样设计
这种顺序保障了安全性和一致性:
- 父类状态先就绪,子类构造方法里能安全访问已初始化的父类字段
- 避免父类构造方法中调用被子类重写的方法时,读到子类字段的默认值(如 null 或 0)
- 所有非静态初始化环节(字段赋值 + 普通代码块)统一归入“实例初始化阶段”,位置不可变
一个典型输出可帮你验证
假设 Father 和 Son 类分别有静态块、普通块、构造方法和成员变量初始化语句,new Son() 的完整输出顺序是:
- Father 静态代码块
- Son 静态代码块
- Father 普通代码块(含父类成员变量初始化)
- Father 构造方法
- Son 普通代码块(含子类成员变量初始化)
- Son 构造方法
只要记住口诀:“先静态后普通,先父类后子类”,再区分清楚哪个阶段(类加载 vs 对象创建),顺序就不会乱。


















