You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单例模式:静态初始化与枚举实现的初始化时机差异

静态初始化与枚举实现单例的实例创建时机差异分析

一、静态初始化单例的创建时机

静态初始化单例是标准的饿汉式(eager initialization),实例创建时机固定在JVM类加载的初始化阶段:

  • 只要类被触发加载(比如调用类的静态方法、访问静态字段、通过Class.forName()加载类等),就会立即初始化静态字段INSTANCE,完成实例创建。
  • 即便后续全程没有调用getInstance()获取实例,只要类被加载,实例就已经存在于内存中。

示例代码:

public class StaticSingleton {
    private static final StaticSingleton INSTANCE = new StaticSingleton();
    
    private StaticSingleton() {}
    
    public static StaticSingleton getInstance() {
        return INSTANCE;
    }
}

二、枚举实现单例的创建时机

枚举实现单例的实例创建时机依赖于枚举类的首次主动使用:

  • 枚举类的实例是在枚举类被触发初始化时创建的,而初始化必须由主动操作触发,比如:访问枚举实例(EnumSingleton.INSTANCE)、调用枚举的静态方法、通过反射获取枚举类的实例等。
  • 如果只是被动加载枚举类(比如通过Class.forName("com.example.EnumSingleton", false, classLoader)这种不触发初始化的方式),枚举实例不会被创建;只有当首次主动使用枚举类时,才会完成实例的初始化。

示例代码:

public enum EnumSingleton {
    INSTANCE;
    
    public void doSomething() {}
}

三、两种实现的场景对比

1. 全程未使用实例的场景

  • 静态初始化单例:只要类被加载(哪怕是被其他类间接依赖触发加载),实例就会被创建。
  • 枚举单例:如果枚举类从未被主动使用,哪怕类被加载,实例也不会被创建,直到有主动操作触发枚举类的初始化。

2. 使用实例的场景

  • 静态初始化单例:实例在类加载阶段就已创建,第一次调用getInstance()只是返回已存在的实例。
  • 枚举单例:第一次访问INSTANCE时触发枚举类初始化,创建实例;后续访问直接返回已创建的实例。

四、枚举实现是否属于饿汉式?

严格来说,枚举实现不属于传统意义上的饿汉式:

  • 传统饿汉式是类加载即初始化实例,而枚举是首次主动使用时才初始化实例,初始化时机更可控。
  • 但由于枚举实例一旦触发初始化就会立即创建,且线程安全由JVM原生保证,部分资料也会将其归为饿汉式的变体——它不会像懒汉式那样延迟到获取实例的方法被调用才初始化,而是在枚举类首次被主动使用时就完成实例创建。

内容的提问来源于stack exchange,提问作者Devesh Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 20:10:36