静态代码块在类初始化阶段执行且仅一次,而非加载阶段;由首次主动使用触发,按源码顺序执行,父类静态块先于子类,异常会导致初始化失败。

静态代码块在JVM中不是类一被加载就执行,而是在「类初始化」阶段才运行,且仅一次;它的触发依赖于首次主动使用,而不是加载本身。
静态代码块的真正执行时机
它发生在JVM类生命周期的「初始化」阶段(Initialization),而非「加载」(Loading)阶段。这个阶段由以下任一操作首次触发:
- 用 new 创建该类的实例
- 调用该类的 public static 方法
- 访问该类的 非编译期常量的 public static 字段(如
public static int PORT = 8080;会触发,但public static final int PORT = 8080;不会) - 通过 Class.forName("X") 反射加载
- 该类作为程序入口(含
main方法)被JVM启动 - 子类初始化时,父类若未初始化,也会被一同触发
多个静态代码块的执行顺序
同一类中定义的多个 static{} 块,严格按源码中从上到下的声明顺序执行。它们和静态变量的显式赋值语句穿插执行——即按书写顺序逐行处理:
- 遇到静态变量声明并带初始化表达式(如
static int a = init();),立即执行该表达式 - 遇到
static{},立即执行其中代码 - 所有静态成员初始化完成后,类才算完成初始化
若任一静态块或静态变量初始化抛出未捕获异常,整个类进入“初始化失败”状态,后续任何主动使用都会直接抛 ExceptionInInitializerError。
继承关系下的静态块执行顺序
当执行 new Child()(Child extends Parent)时,静态部分的执行严格遵循“父优先、先类后子”原则:
- 先触发 Parent 类的初始化:执行 Parent 的全部静态块和静态变量初始化
- 再触发 Child 类的初始化:执行 Child 的全部静态块和静态变量初始化
注意:这个过程只发生一次,即使后续反复 new Child(),静态块也不会再运行。
静态代码块与实例代码块、局部块的本质区别
三者不属于同一机制层级:
- 静态代码块属于类初始化流程,绑定 JVM 的类生命周期
- 实例代码块属于对象初始化流程,在每次构造器调用前自动插入执行(super()之后、构造体之前)
-
局部代码块(方法内
{})纯属语法作用域控制,不参与类或对象初始化,只随方法调用、执行流到达而运行
它们之间没有固定先后关系——局部块可能在静态块之前(如 main 方法开头就有局部块),也可能在之后,取决于代码位置和调用时机。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











