父类静态块先于子类静态块执行,父类普通块和构造方法先于子类普通块和构造方法执行;类加载阶段执行静态内容(父→子),实例化阶段执行非静态内容(父普通块→父构造→子普通块→子构造)。

判断子类与父类在继承链下静态块与构造块的执行先后,关键看两个阶段:类加载阶段和对象实例化阶段。每个阶段都有明确、不可变的顺序规则,不依赖代码书写位置,而是由 JVM 规范强制保证。
类加载阶段:静态内容只执行一次,父类优先
当 JVM 首次主动使用某个类(如 new A()、A.class、调用其静态方法等),会触发该类及其父类的加载与初始化。此时:
- 先检查父类是否已加载;未加载则递归先加载父类
- 父类的静态成员变量赋值(按声明顺序)和静态代码块按文本顺序依次执行
- 父类初始化完成后,再执行子类的静态成员变量赋值和静态代码块(同样按声明顺序)
- 整个过程只发生一次,后续 new 多少对象都不再重复
对象实例化阶段:每次 new 都走一遍,仍坚持父类先行
执行 new A() 时,JVM 创建对象实例,触发实例初始化流程:
- 先为父类所有非静态字段分配空间并设默认值(如 int→0,Object→null)
- 执行父类的普通代码块(即非 static 的 {} 块),按声明顺序
- 执行父类构造方法(隐式或显式 super() 调用)
- 再为子类非静态字段赋初始值(如 int x = 5;)
- 执行子类普通代码块
- 最后执行子类构造方法体
一个典型执行序列(以 new Son() 为例)
假设 Son extends Father,无显式 super(...),则完整输出顺序为:
- Father 静态代码块
- Son 静态代码块
- Father 普通代码块
- Father 构造方法
- Son 普通代码块
- Son 构造方法
注意:若父类构造方法中调用了被子类重写的方法,此时子类字段可能尚未初始化(如仍为默认值 0 或 null),这是常见陷阱。
快速验证技巧
写个最小可运行示例,每个块里加带类名的打印语句,比如:
static { System.out.println("Father static"); }
{ System.out.println("Father init"); }
public Father() { System.out.println("Father ctor"); }
运行 new Son(),观察控制台输出顺序即可直观确认。无需记忆,靠实测最可靠。

















