准备阶段静态变量被赋类型默认零值而非代码初始值,仅处理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 就会在准备阶段直接设成你写的值,跳过零值。
- 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></clinit> 方法完成的。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











