静态代码块是共享资源的“初始化守门人”,它在类加载时线程安全、一次性地初始化static变量,真正实现共享的是static修饰的变量或对象;注意共享不等于线程安全,可变状态仍需同步保护。

静态代码块本身不直接“实现”资源共享,而是为类级别资源共享提供初始化时机和执行保障。真正实现共享的是被 static 修饰的变量或对象,静态代码块只是在类加载时,安全、一次性地把它们准备好。
静态代码块是共享资源的“初始化守门人”
Java 中所有静态变量(类变量)天然具备类级别共享特性——无论创建多少个实例,它们都指向同一份内存。但若初始化逻辑较复杂(比如读配置、建连接、解析 JSON),就不能靠简单赋值完成。这时静态代码块就派上用场:
- 它在类首次被主动使用时触发,由 JVM 保证只执行一次,且线程安全(
<clinit></clinit>阶段加锁) - 适合做耗时、不可重入、依赖外部资源的一次性准备操作
- 能按定义顺序执行多个块,便于分步初始化或调试追踪
典型共享场景:全局配置与工具实例
比如数据库连接参数、日志器、缓存容器等,需要被整个应用统一访问:
- 声明
private static final Config INSTANCE或public static final Logger LOGGER = LoggerFactory.getLogger(...) - 在
static{}块中完成加载、校验、赋值 - 对外提供
public static Config getInstance()或直接暴露public static final字段
这样,任何地方通过 Config.getInstance() 或 Config.INSTANCE 获取的都是同一个对象,自然实现共享。
注意:共享 ≠ 线程安全
静态代码块确保的是“初始化过程”安全,不是“使用过程”安全:
- 如果共享对象内部含可变状态(如
HashMap<string object></string>缓存),多线程并发修改仍需同步(synchronized、ConcurrentHashMap等) -
final修饰能防止引用被篡改,但不保护其内部字段;非 final 静态变量可能被意外重赋值 - 反射或序列化可能绕过构造逻辑,单例需额外防御(
readResolve、私有构造校验)
比纯静态块更稳妥的做法:静态内部类 + 延迟加载
若初始化成本高或依赖运行时环境,可将静态块逻辑移到静态内部类中:
- 利用 JVM 对静态内部类的懒加载机制,实现“用时才初始化”
- 仍享受类加载级线程安全,且天然支持
final引用不可变 - 避免饿汉式提前加载导致启动慢或失败风险
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











