静态变量的显式赋初值在类加载的初始化阶段完成,准备阶段仅赋默认值,初始化阶段执行方法按序执行显式赋值和static{}块,编译期常量除外。

Java 静态变量的显式赋初值(比如 static int x = 10; 或 static { ... })是在类加载的初始化阶段完成的,不是在准备阶段,也不是在类加载完成时或 main 方法开始时。
准备阶段:只分配内存,设默认值
这个阶段 JVM 为所有静态变量在方法区(元空间)分配内存,并赋予类型默认值:
- 整数类型(
int、long等)→0 - 浮点类型 →
0.0 -
boolean→false - 引用类型(如
String、自定义类)→null
注意:static int x = 10; 中的 = 10 此时完全不执行,x 的值仍是 0。
初始化阶段:执行 <clinit></clinit>,真正赋业务值
只有当类被首次主动使用(例如访问非 final 静态字段、调用静态方法、new 实例、Class.forName() 等)时,JVM 才触发该阶段。此时会运行一个由编译器生成的特殊方法 <clinit></clinit>,它包含:
- 所有静态变量的显式赋值语句(按源码从上到下顺序)
- 所有
static{}代码块(同样按出现顺序穿插执行) - 先执行父类的全部静态初始化内容,再执行子类的
这个方法只执行一次,且 JVM 保证线程安全。
例外:编译期常量跳过初始化
声明为 public static final 的基本类型或字符串字面量(如 public static final String MSG = "ok";)属于编译期常量。它们的值在编译时就确定,直接写入常量池,在准备阶段就完成赋值,不会进入初始化阶段,也不生成 <clinit></clinit> 相关逻辑。
常见误解澄清
静态变量不是在类加载完成时初始化,也不是在 main 方法第一行执行时才赋值。它的初始化时机取决于类何时被首次主动使用,早于 main 方法中对该类的第一次实际调用(除非 main 所在类本身是第一个被使用的类)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











