父类静态代码块一定先于子类静态代码块执行,由JVM类初始化机制强制保证:首次主动使用子类时,先完整执行父类静态变量赋值和静态代码块(按源码顺序),再执行子类对应部分,且仅一次。

父类静态代码块一定先于子类静态代码块执行,这是JVM类加载机制强制保证的,不是靠猜或凭经验,而是有明确可验证的路径。
看触发点在哪
谁被首次主动使用,谁就启动整条继承链的初始化。比如调用 Child.staticMethod() 或执行 new Child(),JVM会立即回溯到顶层父类,按继承顺序从上往下完成静态初始化。
- 只调用 Parent.staticMethod() → 只初始化 Parent 类,Child 静态块不执行
- 第一次调用 Child.xxx(任何静态成员)→ 先初始化 Parent 静态部分,再初始化 Child 静态部分
- main 方法写在 Child 类里 → JVM 启动时就会加载 Child,从而提前触发 Parent 初始化,容易误判为“子类先跑”,其实是父类被捎带初始化了
加打印语句直接观察
最简单有效的排查方式:在父类和子类的静态块里各加一行 System.out.println,内容带类名和标识,比如:
-
Parent 类:
static { System.out.println("【Parent static】"); } -
Child 类:
static { System.out.println("【Child static】"); }
然后在独立测试类中分步调用:
立即学习“Java免费学习笔记(深入)”;
- 先调 Child.doNothing() → 输出一定是 【Parent static】在前,【Child static】紧随其后
- 再 new 一个 Child 实例 → 静态块不再输出,说明已执行过且仅一次
- 最后 new Parent 实例 → 不触发 Child 静态块(除非 Child 之前已被使用)
注意编译期常量干扰
某些静态字段看似“用了子类”,其实根本没触发初始化:
-
public static final int VERSION = 1;→ 访问它不会加载类,更不会执行任何静态块 -
public static final String CONF = loadConfig();→ 因为要执行方法,会完整触发类初始化,包括父类静态块
如果发现“该执行的没执行”,先检查访问的是否是编译期常量。
查字节码或用调试器单步
想确认底层行为,可以用 javap -c 查看类字节码,静态初始化逻辑集中在 <clinit> 方法里;或者在 IDE 中对静态块第一行打断点,运行时观察调用栈——你会看到 JVM 内部先调 Parent.<clinit>,再调 Child.<clinit>。
这个顺序不会变,也不受代码书写位置影响,是 JVM 规范硬性要求的。


















