Java允许一个类中定义多个静态代码块,它们按源码顺序合并执行,共同构成一次类初始化过程;执行时机为类首次主动使用时,且仅执行一次。

可以,Java 中静态代码块可以多次定义,且多个静态代码块会按它们在源码中出现的顺序依次执行,仍属于“类初始化阶段的一次整体执行”。
多个静态代码块是合法且常见的
Java 语法允许在一个类中定义多个 static{} 块,编译器会将它们按书写顺序合并到类的 <clinit> 方法中。这不会报错,也不会影响“只执行一次”的语义——所有静态块合起来算作一次初始化过程。
- 多个静态块常用于逻辑分组:比如一个块加载配置,另一个块初始化缓存,第三个注册监听器
- 它们与静态变量初始化语句(如
static int x = initX();)混合执行,顺序严格遵循源码自上而下 - 父类的多个静态块一定先于子类的任何静态块执行
执行时机不变:仍是类首次主动使用时触发一次
无论定义几个静态代码块,只要类由同一个类加载器加载且未卸载,整个初始化流程(包括所有静态块和静态字段赋值)就只发生一次。触发条件没变:
- 首次
new该类实例 - 首次调用该类任意静态方法
- 首次读写该类非
final静态字段 -
Class.forName("X", true, cl)(initialize=true)
注意避免常见陷阱
多个静态块本身没问题,但容易引发隐性问题:
立即学习“Java免费学习笔记(深入)”;
- 若前面的静态块依赖后面才初始化的静态字段,该字段值为默认值(
0、null),而非预期结果 - 某个静态块抛出未捕获异常(如
NullPointerException),会导致整个类初始化失败,后续所有访问都抛ExceptionInInitializerError - 不要在静态块里调用尚未初始化的其他类的静态成员,可能引发循环初始化或死锁
验证方式很简单
在每个静态块里加日志,观察输出顺序和次数:
static { System.out.println("block 1"); }
static { System.out.println("block 2"); }
static { System.out.println("block 3"); }
运行后只会看到三行输出,且仅在第一次触发类初始化时出现——之后哪怕创建一百个对象,也不会再打印。


















