静态代码块适合初始化启动即需、全应用共享且运行期不变的全局资源,如数据库参数、预编译pattern、系统开关等;需用public static final声明、classloader加载、try-catch兜底,并注意路径、空指针、编码等问题。

静态代码块是类加载时执行一次的天然入口,适合初始化那些启动即需、全应用共享、且运行期基本不变的全局资源——它不依赖 Spring 容器,线程安全,但必须手动加载、异常兜底、结果不可变。
哪些资源适合放静态代码块
不是所有配置都该塞进 static {}。真正适合的,是与实例无关、无外部框架依赖、值稳定、且被大量复用的资源:
- 数据库连接串、最大连接数、超时时间等基础参数
- 预编译的正则 Pattern、全局 ObjectMapper 或 JSON 工具实例
- 日志级别开关、监控上报开关等系统级常量
- 从 /app.properties 或 config.yml 手动读取的基础配置
怎么写才真正“只执行一次”
光写 static{} 不够。关键在三点:顺序、容错、不可变。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 把字段声明为 public static final,防止后续被修改
- 用 ClassLoader.getResourceAsStream() 加载资源,不能用 @Value(此时 Spring 还没启动)
- 所有 IO 操作必须 try-catch,捕获后转为 ExceptionInInitializerError,避免静默失败
- 多个静态变量和块按源码顺序执行,把强依赖项(如配置对象)放在前面
避开高频陷阱
看似简单,实则容易翻车。常见问题有:
- 路径写成 "/app.properties"(带斜杠)→ 会从 classpath 根外查找,应写 "app.properties"
- 没判空 InputStream → getResourceAsStream() 返回 null 时直接 NPE
- Properties.load() 不指定编码 → 中文乱码(Java 8+ 默认 ISO-8859-1,建议用 load(new InputStreamReader(is, "UTF-8")))
- 在块里做 HTTP 请求或大文件解析 → 阻塞类加载,拖慢整个应用启动
需要懒加载?试试静态内部类
如果资源初始化开销大(比如构建大型缓存、初始化连接池),又不想在应用启动时就执行,可用静态内部类模式:
- 把耗时逻辑封装进 static class Holder 的静态块中
- 对外暴露 public static final Resource INSTANCE = Holder.INSTANCE
- Holder 初始化仅在首次访问 INSTANCE 时触发,且 JVM 保证线程安全和异常隔离
- 即使 Holder 初始化失败,外层类仍可正常使用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










