静态代码块用于类加载时一次性初始化类级别数据,语法为static{...},在类首次主动使用时由jvm线程安全执行一次,按源码顺序执行且父类优先;不可访问this及非static成员;常用于配置、工具实例、共享缓存等全局资源准备,需避免异常和耗时操作。

静态代码块用来在类加载时一次性完成类级别数据的初始化,它不依赖对象创建,天然适合配置、工具实例、共享缓存等全局资源的准备。
静态代码块的基本写法和执行时机
语法很简单:用 static { ... } 定义,不带方法名、参数或返回值。它在类首次被主动使用(如 new 实例、调用静态方法、访问非 final 静态字段)时,由 JVM 自动执行一次,且线程安全。
- 多个静态块按源码中出现顺序依次执行
- 父类的静态块一定先于子类执行
- 不能访问 this、非 static 字段或方法,否则编译失败
初始化类级别数据的常见方式
真正被共享的是 static 修饰的变量,静态代码块只是把它们“准备好”。典型做法包括:
- 声明 private static final List
CODE_LIST ,在块中用 new ArrayList() 初始化并 add 数据 - 声明 private static Config config,在块中读取 properties 文件并解析赋值
- 声明 public static final Logger log,在块中获取实例并设置 MDC 或日志级别
- 配合 ImmutableList.copyOf() 或 Map.ofEntries() 构建不可变集合,避免后续误修改
需要注意的关键细节
看似简单,但几个点容易出问题:
- 块里抛出未捕获异常(如 IOException、ClassNotFoundException),会导致类加载失败,之后所有对该类的引用都会报 NoClassDefFoundError
- 不要在块里做耗时操作(如远程调用、大文件读取),会拖慢整个应用启动
- static final 基本类型常量(如 public static final int PORT = 8080;)不会触发类初始化,所以它的值是编译期内联的,不走静态块
- 若初始化逻辑复杂或依赖运行时环境,可改用静态内部类 + 延迟加载,既保持线程安全,又实现“用时才初始化”
一个实用示例:初始化共享的学生列表
比如学生管理系统中需要一份预置的静态学生数据:
- 声明 private static final List
STUDENTS - 在 static {} 中 new ArrayList(),然后 add(new Student(...)) 多个实例
- 最后用 Collections.unmodifiableList() 包一层,防止外部修改
- 对外提供 public static List
getStudents() 方法供其他类安全读取
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











