静态代码块是类加载时执行一次的全局初始化机制,适合预加载启动即需、全应用共享且运行期不变的资源,如配置参数、预编译Pattern、驱动注册等;需声明public static final、用ClassLoader安全读取资源、try-catch兜底并指定UTF-8编码,避免耗时操作与Spring依赖。

静态代码块是 Java 类加载过程中执行全局初始化任务最直接、最轻量的机制——它在类首次被主动使用前自动触发,只运行一次,天然线程安全,适合完成启动即需、全应用共享、运行期不变的预设工作。
适合放进静态代码块的全局任务
不是所有初始化都该放这里。真正匹配的,是那些“类一加载就得就绪”的基础能力:
-
配置加载与常量挂载:读取
app.properties或config.yml,解析为public static final字段(如数据库 URL、超时毫秒数) -
不可变工具实例构建:预编译正则
Pattern、初始化ObjectMapper、创建线程安全的DateTimeFormatter -
驱动注册与框架绑定:显式调用
Class.forName("com.mysql.cj.jdbc.Driver")(JDBC 4.0+ 可省略,但兜底或定制场景仍适用) -
系统级开关与日志准备:从配置中读取
enable.metrics开关,或提前获取Logger实例并输出启动日志
写法要点:顺序、容错、不可变
光有 static{} 不够,关键在三件事:
- 把强依赖项(比如配置对象)声明和初始化块写在前面,避免后面字段引用
null - 所有 IO 操作必须包裹
try-catch,捕获后转为ExceptionInInitializerError,防止静默失败 - 资源加载路径用
"app.properties"(不加斜杠),InputStream先判空再使用,Properties.load()显式指定UTF-8编码 - 结果字段一律声明为
public static final,确保后续不可篡改
避开高频翻车点
看似简单,实则容易出问题:
立即学习“Java免费学习笔记(深入)”;
- 在块里发起 HTTP 请求、解析百兆 JSON 文件——会卡住整个类加载,拖慢启动甚至超时失败
- 调用尚未初始化的其他类静态方法(尤其跨模块时),可能引发死锁或
NoClassDefFoundError - 误用
this或调用非静态方法——此时对象根本不存在,编译直接报错 - 依赖 Spring 环境(如
@Value、ApplicationContext)——此时容器还没启动,必定null
大开销任务怎么办?用静态内部类延迟加载
如果初始化逻辑很重(比如构建百万级缓存、初始化连接池),又不想阻塞启动,推荐“静态内部类 Holder 模式”:
- 把耗时逻辑封装进
private static class Holder的静态块中 - 对外暴露
public static final Resource INSTANCE = Holder.INSTANCE - Holder 的初始化仅在首次访问
INSTANCE时触发,JVM 保证线程安全且异常隔离 - 即使 Holder 初始化失败,外层类仍可正常使用,不影响其他功能


















