java类变量的内存分配和默认零值设置在类加载准备阶段完成,jvm在方法区分配内存并按类型赋零值(数值0、boolean false、引用null),但不执行任何java代码;编译期常量(static final + 字面量)直接赋值,其余static变量(含非final或运行期final)先设零值,初始化阶段再赋真实值。

Java 中类变量(即 static 字段)的内存分配和初始值设置,是在 JVM 类加载的准备阶段(Preparation Phase)自动完成的。这个过程由虚拟机严格控制,开发者不能干预,也不执行任何 Java 代码。
准备阶段只做两件事:分配内存 + 设默认零值
该阶段发生在类加载流程的第二步(加载之后、初始化之前),JVM 在方法区(Method Area)为所有类变量分配内存空间,并按数据类型赋予默认零值:
- 数值类型:int/short/byte/char → 0;long → 0L;float → 0.0f;double → 0.0d
- 布尔类型:boolean → false
- 引用类型(如 String、List、自定义类等)→ null
注意:这个“零值”是 JVM 规定的初始状态,不是你在代码里写的值。比如 static int count = 100;,此时 count 在准备阶段仍是 0,100 要等到初始化阶段才写入。
哪些 static 变量会走零值流程
只有满足以下条件的类变量,才会在准备阶段被设为零值:
- 被 static 修饰,且未用 final 修饰(如
static String name;或static int id;) - 虽用了 static final,但值在运行期才能确定(如
static final long ts = System.nanoTime();)——这类先设为 0L,初始化阶段再调用方法赋真值
而像 public static final int MAX = 100; 或 static final String MSG = "ok"; 这类编译期常量,会在准备阶段直接写入 100 或 "ok",跳过零值步骤。
准备阶段明确不做的事
这个阶段非常“克制”,它不会:
- 执行任何静态代码块(
static {}) - 执行静态变量的显式赋值语句(如
static int x = 5;中的= 5) - 调用任何方法(包括
getValue()这样的静态方法) - 处理实例变量(非 static 字段)——它们在 new 对象时才分配在堆上
换句话说,准备阶段只是给 static 变量“搭好架子、留好位置”,真正“填内容”要等到后面的初始化阶段,由 <clinit></clinit> 方法统一执行。
一个可验证的小例子
写一个类:
class Test {
static int a;
static final int b = 200;
static final int c = getValue();
static { System.out.println("static block"); }
static int getValue() { return 300; }
}
当首次主动使用 Test.a 时:
- 准备阶段:为
a分配内存并设为 0;b直接设为 200;c先设为 0 - 初始化阶段:
c被getValue()赋值为 300,然后执行static{}块打印日志
所以你看到的 a 初始值是 0,不是未定义;c 在 static 块执行前就已经是 0 —— 这正是准备阶段生效的证据。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











