静态代码块适用于类加载时一次性初始化复杂静态成员,如读取配置、预加载缓存、处理异常资源、构建单例及全局设置;须用static{}定义,按源码顺序执行,不可用this或非静态方法。

静态代码块适合初始化那些无法在声明时直接赋值、又必须在类加载阶段就完成构建的复杂成员结构——比如依赖外部配置、需异常处理、涉及多步逻辑或资源预热的静态对象。
静态代码块适用的典型场景
它不是万能初始化工具,而是专用于“类加载时一次性执行”的关键初始化任务:
- 读取配置文件并解析为静态常量(如数据库连接池参数)
- 预加载不可变缓存(如枚举映射表、地区码字典)
- 初始化需要 try-catch 处理的资源(如 Class.forName 加载驱动)
- 构建单例实例,尤其当构造过程可能失败或需日志记录时
- 执行带副作用的全局设置(如注册JVM shutdown hook)
正确写法与常见错误
静态代码块必须用 static {} 包裹,且只能出现在类体中(不能在方法内)。它和静态字段按源码顺序依次执行:
- 先执行前面定义的静态字段显式初始化(如
private static final List<string> NAMES = Arrays.asList("A", "B");</string>) - 再执行同位置之前的静态代码块(
static { ... }) - 若静态字段依赖静态块结果,务必把块写在字段声明之前
- 禁止在静态块中使用
this或调用非静态方法——此时实例尚不存在 - 抛出的异常会被包装成
ExceptionInInitializerError,导致后续类加载失败
与其它初始化方式的协作关系
静态代码块不是孤立存在的,它和其它静态初始化手段共同构成类加载阶段的完整初始化链:
- 静态字段就地初始化(简单值、不可变对象)优先用这种方式,更简洁安全
- 静态代码块用于补充就地初始化做不到的事:条件判断、循环、IO、异常捕获
- 两者混合时,JVM严格按代码书写顺序执行,不跨行跳过
- 不要试图在静态块里初始化实例变量(如
name = "test"),这会导致编译错误 - 如果初始化逻辑可复用或需测试,建议提取为私有静态方法,在块中调用
继承环境下的执行顺序
子类使用父类静态成员时,会触发整个继承链的静态初始化,顺序固定:
- 先加载并初始化父类的静态字段和静态块(按源码顺序)
- 再加载并初始化子类的静态字段和静态块(同样按源码顺序)
- 这个过程只发生一次,无论创建多少子类实例
- 父类静态块中不能访问子类的静态字段(子类此时还未加载)
- 可通过
Class.forName("SubClass", true, loader)主动触发子类加载,从而提前完成其静态初始化
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











