Java类初始化阶段静态代码块与静态变量赋值按源码从上到下顺序合并进<clinit>方法执行,父类优先于子类,且只执行一次;任一未捕获异常将终止初始化并导致后续访问抛NoClassDefFoundError。

Java 类初始化阶段执行静态代码块和静态变量赋值,核心就一条:**按源码从上到下的顺序,合并进 <clinit> 方法统一执行,父类优先、只执行一次。**
静态部分全部合并进一个 <clinit> 方法
编译后,所有静态变量的显式赋值(如 static String s = init();)和所有 static{} 块,都会被 JVM 收集到同一个特殊方法 <clinit> 中:
- 谁在 Java 源文件里写得靠前,谁的初始化逻辑就先插入字节码指令
-
static int a = getValue();在static{ b = 1; }上方 →getValue()先调用 - 哪怕只声明不赋值(如
static String x;),它在准备阶段已被设为null,但显式初始化动作仍按位置发生
父子类之间强制分层:先父类,再子类
只要触发子类的首次主动使用(比如 new Child() 或 Child.doWork()),JVM 就会严格按以下顺序完成初始化:
- 父类所有静态变量赋值(按父类源码顺序)
- 父类所有静态代码块(按父类源码顺序)
- 子类所有静态变量赋值(按子类源码顺序)
- 子类所有静态代码块(按子类源码顺序)
父类静态块中不能安全访问子类静态字段;子类静态块可放心读取父类已初始化的 public static 字段。
立即学习“Java免费学习笔记(深入)”;
异常会中断整个初始化流程
任一静态初始化语句抛出未捕获异常(如 NullPointerException、ExceptionInInitializerError):
-
<clinit>立即终止,类进入“初始化失败”状态 - NoClassDefFoundError
- 该类无法再次尝试初始化——JVM 不允许重试
注意非法前向引用
静态块中不能读写其后才声明的静态变量,Java 编译器会直接报错:
-
static{ flag = 1; } static int flag;→ 编译失败(illegal forward reference) -
static{ System.out.println(flag); } static String flag = "ok";→ 同样编译失败 - 这说明 JVM 不看“变量是否存在”,而严格依赖文本顺序判断可用性


















