父类静态代码块一定先于子类静态代码块执行,由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】"); }
然后在独立测试类中分步调用:
- 先调 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 查看类字节码,静态初始化逻辑集中在
这个顺序不会变,也不受代码书写位置影响,是 JVM 规范硬性要求的。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











