静态块适合一次性配置加载,但只执行一次、不支持热更新、对路径和异常敏感;应通过类路径加载资源、处理空流与编码、用枚举替代魔法数字,并避免在热部署中依赖其刷新。

静态块适合做一次性的配置加载,但必须清楚它只执行一次、不支持热更新、对路径和异常敏感。用好了能消除硬编码、提升语义表达;用错了会卡死类初始化、掩盖配置错误、导致启动失败。
静态块读配置的正确写法
别用 FileInputStream("config.properties") —— 打包后必报错。应优先走类路径加载,并处理空流和编码问题:
- 用 Class.getClassLoader().getResourceAsStream("application.properties") 获取输入流
- 流为 null 时要有明确 fallback(如读系统属性指定的绝对路径)或直接抛运行时异常
- Properties.load() 在 Java 8+ 默认按 ISO-8859-1 解码,含中文需改用 load(new InputStreamReader(is, "UTF-8"))
- 所有赋值操作放在 try 内,避免部分字段未初始化就抛异常导致类加载失败
用枚举替代魔法数字:静态块 + 配置联动
把配置里的数字映射成枚举成员,不只是“提常量”,而是赋予业务含义和校验能力:
- 定义枚举时带构造参数,如 ORDER_PENDING(1)、ORDER_SHIPPED(2)
- 静态块中读到 order.status.pending=1 后,不做 int status = 1,而是确认 OrderStatus.PENDING 已存在
- 在枚举内补充 public static OrderStatus fromCode(int code),遍历 values() 匹配,找不到就抛 IllegalArgumentException
- 数据库查询、接口返回、条件判断全部使用枚举引用,IDE 可提示、编译器可校验、重构可联动
热部署下配置不生效?这不是 bug,是机制
Spring Boot DevTools 或 Tomcat 热重启时,静态块不会重跑。因为新类由新类加载器加载,静态变量是全新的、空的——旧值留在老加载器里,无法自动同步。
立即学习“Java免费学习笔记(深入)”;
- 不要指望改完 properties 文件再点 “Restart” 就能刷新 static 变量
- 开发期可加 /actuator/refresh 端点(配合 @ConfigurationProperties + @RefreshScope)
- 生产环境建议放弃静态块托管配置,改用 Spring 的配置绑定机制或监听文件变更后主动 reload
- 若坚持用静态块,至少保证它只加载启动即固定、后续绝不变更的基础参数(如加密盐值、默认超时毫秒数)
避坑要点:三不原则
静态块不是万能初始化容器,守住边界才能稳定:
- 不调用本类其他静态方法:可能触发类初始化循环,JVM 报 ExceptionInInitializerError
- 不放耗时操作:远程请求、大文件解析、复杂计算都会拖慢整个类加载,影响应用启动速度
- 不设默认值掩盖缺失项:配置项 order.status.cancelled 缺失时,应明确失败,而不是悄悄设成 0 导致逻辑错乱


















