静态初始化块是类加载时执行一次的天然入口,适合配置启动即需、全应用共享、运行期基本不变的类变量,如数据库连接字符串、预编译Pattern、系统级开关及classpath配置项;须声明为public static final,手动读取资源并异常兜底,避免热部署重复执行或非编译期常量导致的类重加载。

静态初始化块是类加载时执行一次的天然入口,适合配置那些启动即需、全应用共享、运行期基本不变的类变量。它不依赖 Spring 容器,也不需要手动触发,但必须写对才能真正“一次性”生效。
哪些类变量适合用静态块配置
不是所有静态变量都该放进 static {}。优先考虑以下几类:
- 数据库连接字符串、最大线程数、超时毫秒值等基础参数
- 预编译的正则 Pattern、复用的 ObjectMapper 或 Gson 实例
- 日志级别开关、监控上报开关等系统级布尔常量
- 从 classpath 加载的 config.properties 或 app.yml 中读取的原始配置项
正确写法:声明 + 加载 + 异常兜底
关键不是写个 static {} 就完事,而是确保结果可靠、失败可见、后续不可篡改:
- 变量声明为 public static final,防止被意外修改
- 用 Properties 或 InputStream 手动读取资源,不能调用 @Value 或 Environment(此时 Spring 还没启动)
- 所有 IO 操作必须包裹 try-catch,捕获后转为 ExceptionInInitializerError,避免静默失败
- 多个静态变量和块按源码顺序执行,把强依赖项(如配置文件路径)放在前面
避开常见陷阱
看似只执行一次,实际可能重复或失效,原因往往在环境或写法:
立即学习“Java免费学习笔记(深入)”;
- 热部署重启时,旧类加载器未卸载,新加载器会再次执行 static {}
- static final 字符串若由 System.getProperty() 构造,就不是编译期常量,每次访问都会触发类加载
- 在块里调用非静态方法或使用 this —— 此时对象根本不存在,编译直接报错
- 误以为“只要写了 static {},每次读字段就执行”,其实只在类首次主动使用时运行一次
推荐搭配:静态内部类实现延迟+安全
如果配置加载耗时,或希望首次调用 getInstance() 时才初始化,比直接 static {} 更优:
- 外部类只保留私有构造和 public static getInstance()
- 静态内部类中定义 private static final 实例,并在内部类静态块中构建
- JVM 保证该内部类仅在 getInstance() 首次被调用时加载,整个过程原子且线程安全
- 既规避了类提前加载开销,又保留了类加载级的初始化保障


















