Java静态代码块在类首次被JVM主动使用进入初始化阶段时执行且仅一次;触发条件包括new实例、调用静态方法、访问非final静态字段、Class.forName反射加载或运行main主类,按源码顺序执行,不可访问实例成员。

Java静态代码块不是一写就跑,也不是类一加载就执行——它只在类首次被JVM主动使用、进入“初始化阶段”时运行一次,且严格按源码顺序执行。
静态代码块何时真正触发
只有以下操作才会让JVM启动类的初始化流程,从而执行静态代码块:
- 用new创建该类的第一个实例
- 调用该类的任意static方法
- 访问该类的非final静态字段(如public static String HOST = "localhost";)
- 通过Class.forName("X")反射加载(注意:ClassLoader.loadClass("X")不会触发)
- JVM启动时直接运行含main()的主类
反例:仅声明变量、导入类、或访问public static final int PORT = 8080;这类编译期常量,都不会触发初始化。
执行顺序由源码位置决定
静态代码块和静态变量赋值语句混合在一起,按源码从上到下交替执行:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 先出现的static {}先执行
- 先声明的static int x = init();也先求值
- 若init()内部引用了后面才声明的静态字段,该字段值仍为默认值(如null或0)
- 父类静态内容一定在子类之前完成,这是JVM强制保证的
适合放什么,不适合放什么
静态代码块是轻量、确定、一次性初始化的理想位置:
- 用Class.getResourceAsStream()加载本地配置文件
- 构建不可变静态集合,比如Map.of("a", 1, "b", 2)
- 利用JVM类初始化锁实现线程安全单例
- 校验必要环境变量或系统属性是否存在
应避免:
- 远程HTTP调用、数据库连接等可能阻塞或失败的操作
- 启动新线程并等待其完成
- 访问其他尚未初始化完成的类的静态资源(易引发循环依赖)
容易忽略的关键细节
看似简单,但在真实环境中容易误判:
- 热部署、DevTools、OSGi等场景下,同一类可能被多个类加载器分别加载,每个都会独立执行一次静态块
- 若静态块中抛出未捕获异常(包括ExceptionInInitializerError),该类即进入“初始化失败”状态,后续所有访问都直接报NoClassDefFoundError
- 子类访问父类的非final静态字段,也会触发父类初始化——哪怕你没碰过父类本身

















