Java静态变量显式初始化和静态代码块在类加载的初始化阶段执行,而非加载或准备阶段;准备阶段仅分配内存并设默认值,初始化阶段才执行赋值和static{}块,且按源码顺序执行。

Java 静态变量的初始化发生在类加载的初始化(Initialization)阶段,不是加载(Loading)或准备(Preparing)阶段。
初始化阶段才真正赋值
虽然静态变量在准备阶段就被分配内存并设为默认值(如 int 为 0、Object 为 null),但你代码里写的 static int x = 10; 或 static String s = "hello"; 这类显式赋值,要等到初始化阶段才执行。这个阶段还会运行所有静态代码块(static {}),且只执行一次。
- 初始化由 JVM 主动触发,常见触发条件包括:首次 new 实例、首次访问/赋值非 final 静态字段、首次调用静态方法、反射加载(
Class.forName("X", true, cl))等 - 若用
Class.forName("X", false, cl),则跳过初始化,此时静态变量仍为默认值(如 0 或 null)
准备阶段只是“占位”,不执行你的逻辑
准备阶段只做两件事:为 static 变量分配内存 + 设 Java 规定的默认初始值。它不执行任何构造逻辑、不调用方法、不运行静态块。比如 static String s = init(); 中的 init() 方法,在准备阶段完全不会被调用。
- final static 常量(编译期常量)例外:它们可能在准备阶段就直接赋值为字面量值(如
static final int N = 123;) - 普通 static 变量和静态块全部延迟到初始化阶段,按源码中出现的顺序依次执行
验证是否进入初始化阶段的小技巧
打印某个静态变量的值,就能判断当前走到哪一阶段:
立即学习“Java免费学习笔记(深入)”;
- 看到 0、false、null → 只到准备阶段(例如用
Class.forName(..., false)加载后未触发主动使用) - 看到你代码里写的实际值(如 10、"hello"、或 init() 的返回结果)→ 已完成初始化阶段
父子类之间的初始化顺序也依赖该阶段
子类初始化时,JVM 会强制先完成父类的初始化——也就是说,父类的静态变量赋值和静态块一定在子类之前执行,这个约束正是靠初始化阶段的触发规则保证的,而不是靠加载顺序。
- 即使你直接引用子类的静态字段,也会先拉起父类的
<clinit>方法执行完毕,再执行子类的 - 整个过程由 JVM 自动保障,开发者无法绕过或调整该阶段的执行时机


















