准备阶段静态变量被赋类型默认零值而非代码初始值,仅处理static变量,final static编译期常量除外;不执行任何Java代码,内存分配与初值设定由JVM规范定义。

静态变量在准备阶段被赋予的是类型默认的零值,不是代码里写的初始值,这个阶段不执行任何 Java 代码,只是 JVM 为 static 变量 分配内存并设初值。
准备阶段只处理 static 变量
只有被 static 修饰的类变量 才会在准备阶段分配内存和设初始值;实例变量(没 static)此时完全不参与,它们要等到对象创建时才在堆中分配。
- public static int a = 10; → 准备阶段 a = 0(不是 10)
- public static Object obj; → 准备阶段 obj = null
- public static boolean flag; → 准备阶段 flag = false
- public final int x = 5; → 不是 static,准备阶段不处理,留到实例初始化
零值有明确对应规则
每种类型在准备阶段的“零值”是固定的,由 JVM 规范定义:
- 数值类型:int/short/byte → 0,long → 0L,float → 0.0f,double → 0.0d
- 字符类型:char → '\u0000'
- 布尔类型:boolean → false
- 引用类型:所有类、数组、接口等 → null
final static 是例外,但有条件
如果一个变量同时满足 static + final,且赋值是编译期常量(比如字面量或常量表达式),JVM 就会在准备阶段直接设成你写的值,跳过零值。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
- public static final int PORT = 8080; → 准备阶段就是 8080
- public static final String MSG = "OK"; → 准备阶段就是 "OK"
- public static final int R = new Random().nextInt(); → 不是编译期常量,准备阶段仍是 0,真正赋值在初始化阶段
准备阶段不执行任何逻辑
这个阶段没有字节码执行,不会调用方法、不会运行静态代码块、也不会触发类初始化。它纯属 JVM 内部的内存预分配与初值设定动作,发生在类加载连接过程的第二步,早于初始化阶段。
真正把 public static int a = 10; 中的 10 赋给 a 的操作,是在初始化阶段通过 <clinit> 方法完成的。

















