静态代码块和静态变量赋值在类初始化阶段执行且仅一次,由jvm按源码顺序交替执行,父类优先于子类;触发条件包括new实例、调用静态方法、访问非final静态字段、class.forname反射加载或运行main主类。

静态代码块和静态变量赋值,是在类的初始化阶段执行的,不是加载时、也不是每次 new 时,而是在类首次被主动使用时,统一由 JVM 执行一次。
初始化阶段才真正开始赋值和执行
类加载过程分为加载、链接(含准备)、初始化三个关键阶段:
- 准备阶段:JVM 为所有 static 变量分配内存,并设默认值(如 int 为 0、Object 为 null),但不执行任何代码
-
初始化阶段:JVM 才真正执行 static 变量的显式赋值语句(如
static int x = 5;)和所有static{}块——它们被合并进一个叫<clinit></clinit>的特殊方法,按源码顺序逐行执行
哪些操作会触发初始化(即跑静态块)
只有满足以下任一条件,JVM 才进入初始化阶段,执行静态代码块和赋值:
- 用
new创建该类第一个实例 - 调用该类的任意静态方法(如
MyClass.doWork()) - 访问或修改非 final 的静态字段(如
MyClass.count++) - 通过
Class.forName("MyClass")反射加载(注意:ClassLoader.loadClass()不触发) - JVM 启动时直接运行含
main()的主类 - 初始化子类时(此时父类一定先完成初始化)
反例:声明变量、创建该类数组、引用 public static final String MSG = "ok"; 这类编译期常量,都不会触发初始化。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
静态内容执行顺序严格按源码书写位置
同一个类里,静态变量赋值和静态代码块混合在一起,谁写在上面,谁先执行:
-
static String a = initA();→ 立即调用initA() -
static { b = "ok"; }→ 紧接着执行该块 -
static int c = a.length() + 1;→ 此时a已有值,b也已赋值
若 initA() 中提前读取后面才定义的 static String d,此时 d 还是 null(或默认值),不会编译报错,但可能引发空指针。
继承场景下:父类静态内容一定先于子类
例如执行 new Child() 时,顺序固定为:
- 先完整执行
Parent类中所有静态变量赋值 +static{}块(按 Parent 源码从上到下) - 再执行
Child类中所有静态变量赋值 +static{}块(按 Child 源码从上到下)
这个过程只发生一次。后续再 new 或调用静态方法,不会再重复执行静态块。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










