静态代码块在类加载初始化阶段执行一次,适合轻量级类级数据初始化;需用ClassLoader安全加载资源、判空、显式处理编码与异常、保证赋值顺序和不可变性,并避开路径错误、阻塞操作等陷阱。

静态代码块在类加载的初始化阶段执行一次,适合做轻量、确定、无依赖容器的类级数据初始化——比如读取配置、预编译工具对象、挂载常量等。它不等待 Spring 启动,也不需要手动调用,但必须写对路径、判空、编码和异常处理。
用 ClassLoader 安全加载 classpath 资源
不能用 new FileInputStream() 或硬编码绝对路径,打包后必然失败。正确方式是:
- 调用 MyClass.class.getClassLoader().getResourceAsStream("config.properties"),路径不加斜杠,表示从 classpath 根目录查找
- 若资源与当前类同包,可用 MyClass.class.getResourceAsStream("app.conf")
- 返回值可能为 null,必须先判空再使用,否则直接抛 NullPointerException
显式处理编码与异常,避免乱码和静默失败
Properties 默认按 ISO-8859-1 解码,中文会乱码;IO 异常若被吞掉,会导致类初始化中断,后续访问抛 NoClassDefFoundError:
- 用 props.load(new InputStreamReader(is, "UTF-8")) 显式指定编码
- 所有流操作必须套 try-with-resources,确保自动关闭
- 捕获 IOException 后,统一包装为 ExceptionInInitializerError,带清晰上下文,例如 "Failed to load config.properties: file not found or unreadable"
- 字段赋值(如 TIMEOUT = Integer.parseInt(...))必须放在 try 块内,防止部分成功、部分失败
保证顺序、不可变与线程安全
静态变量和静态代码块按源码自上而下交替执行,且父类优先于子类。关键点:
- 把强依赖项(如配置对象、工具实例)声明和初始化写在前面,避免引用未初始化的 null 字段
- 结果应赋给 public static final 字段,例如 public static final Map
CONFIG ,配合 Collections.unmodifiableMap() 防止误修改 - JVM 保证类初始化过程的原子性与可见性,天然线程安全,无需额外同步
避开常见陷阱
看似简单,实则容易出错:
- 路径写成 "/app.properties"(带斜杠)→ 会从 classpath 根外查找,应写 "app.properties"
- 在静态块里做 HTTP 请求、解析大文件或连数据库 → 阻塞类加载,拖慢启动,甚至导致超时失败
- 访问 public static final int PORT = 8080 这类编译期常量 → 不触发类初始化,静态块不会运行
- 热部署或多个 ClassLoader 环境下(如 Tomcat、OSGi),同一类被不同加载器加载,每个都会独立执行一遍静态块
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











