类变量的内存分配和默认初始化在JVM类加载的准备阶段完成,此时为static字段分配内存并设为零值(如int为0、引用为null),但不执行static代码块或显式赋值。

在 Java 中,类变量(即用 static 修饰的字段)的内存分配和默认初始化是在类的 准备阶段(Preparation Phase) 完成的,这是 JVM 类加载过程中的一个固定步骤,由虚拟机自动执行,开发者无需手动干预。
准备阶段做了什么
准备阶段是类加载的第二步(在加载之后、初始化之前),JVM 为类的 静态变量(类变量)分配内存,并将其设置为该类型的 **默认零值**(zero value),例如:
- int / short / byte / char / boolean → 0(或 '\u0000' / false)
- long → 0L,float → 0.0f,double → 0.0d
- 引用类型(如 String、Object 等)→ null
注意:这个阶段不执行任何 Java 代码(比如 static 块或赋值语句),也不调用构造器。它只处理“被 static 修饰且未被 final 修饰”的变量的内存分配与零值设定。
哪些变量会在准备阶段初始化为零值
仅以下两类静态变量参与准备阶段的零值设置:
- 普通 static 字段(无显式初始值,也未用 final 修饰)
- static final 字段,但其值是编译期常量(如
static final int MAX = 100;)——这类会直接赋常量值,跳过零值阶段;而运行期才能确定的 final 静态变量(如static final long TIME = System.currentTimeMillis();)仍先设为 0L,到初始化阶段再赋值
准备阶段不做的事
避免常见误解:
- 不会执行 static 代码块(
static { ... }) - 不会执行 static 变量的显式赋值语句(如
static int x = 5;中的= 5部分)——这部分在初始化阶段才执行 - 不涉及实例变量(非 static 字段),它们在对象实例化时才分配内存
一个直观的例子
考虑如下类:
class Demo {
static int a; // 准备阶段:分配内存,设为 0
static final int b = 10; // 编译期常量,准备阶段直接设为 10(不走零值)
static final int c = getValue(); // 运行期常量,准备阶段设为 0,初始化阶段再调用 getValue()
static { System.out.println("init block"); } // 初始化阶段才执行
static int getValue() { return 20; }
}
当 JVM 加载 Demo 类时:
- a 在准备阶段被分配内存并设为 0
- b 在准备阶段就直接写入 10(因是常量表达式)
- c 先被设为 0(准备阶段),到初始化阶段才调用 getValue() 赋值为 20
- static 块在初始化阶段执行,此时所有静态变量已分配好内存(包括零值或常量值)

















