怎么通过准备阶段为类变量分配内存并设置默认初始零值

在 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 块在初始化阶段执行,此时所有静态变量已分配好内存(包括零值或常量值)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。