java中静态变量赋值发生在类初始化阶段,而非加载时;仅当类首次被主动使用(如new实例、调用静态方法、访问非final静态字段等)才触发,按源码顺序执行静态变量显式赋值和静态代码块,父类优先于子类。

Java 中静态变量的赋值发生在类的初始化阶段(Initialization),不是类一加载就立刻赋值,而是等到该类被首次主动使用时才真正执行赋值逻辑。
什么时候触发赋值?
以下任一操作会触发类初始化,从而执行静态变量的显式赋值和静态代码块:
- 访问该类的非 final 静态字段(如
MyClass.value) - 调用该类的静态方法
- 用
new创建该类的实例 - 通过反射调用
Class.forName("MyClass")(第二个参数为true或省略) - 初始化子类时,若父类尚未初始化,则先触发父类初始化
- JVM 启动时指定的主类(含
main方法的类)
赋值具体发生在哪个阶段?
类加载过程分为五个阶段:加载 → 验证 → 准备 → 解析 → 初始化。静态变量的赋值只在初始化阶段发生:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
准备阶段:JVM 仅为静态变量分配内存,并设默认值(
int为0,对象引用为null),你写的static int x = 10;还没执行 -
初始化阶段:JVM 执行类构造器
<clinit></clinit>方法,它由编译器自动生成,按源码中从上到下的顺序,依次执行所有静态变量的显式赋值语句和static{}块
赋值顺序怎么确定?
同一类中,静态成员严格按源码文本顺序执行:
- 谁写在前面,谁先执行——哪怕一个
static{}块出现在变量声明之前,它也按书写位置生效 - 例如:
static int a = 5;在前,static int b = a + 1;在后,则b得到6;反之,a此时还是默认值0,b就是1 - 未显式赋值的静态变量(如
static int y;)在准备阶段已为0,但“显式初始化”仍遵循声明位置
哪些情况不会触发赋值?
这些属于“被动引用”,不触发类初始化,静态变量保持默认值(0、null 等):
- 通过子类访问父类的静态字段(如
Child.PARENT_FIELD) - 仅定义数组类型(如
MyClass[] arr;) - 使用
MyClass.class获取 Class 对象(未进一步主动使用) - 访问
static final编译期常量(如static final String MSG = "ok";),其值已在准备阶段直接写入,不走初始化
父子类之间怎么处理?
子类首次主动使用时,JVM 强制保证父类先完成全部静态初始化:
- 先执行父类中所有静态变量赋值 + 静态块(按父类源码顺序)
- 再执行子类中所有静态变量赋值 + 静态块(按子类源码顺序)
- 因此子类静态块可安全读取父类 public static 字段,但父类不能依赖子类的静态变量
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










