Skip to content

源码:labs/java/runtime-concurrency/singleton-dcl/src/InnerClassSingleton.java

  • 原始路径:labs/java/runtime-concurrency/singleton-dcl/src/InnerClassSingleton.java
  • 类型:java
java
/**
 * 静态内部类(Holder)单例。
 *
 * 特点:
 * - 懒加载:首次 getInstance() 才加载 Holder,触发 static 字段初始化
 * - 线程安全:✅ JVM 类初始化 <clinit> 互斥,天然只执行一次
 * - 性能:⚡ 无锁,创建后 get 仅为字段读取
 * - 复杂度:低,无 volatile / 双重检查,Java/Android 工程首选之一
 *
 * Java 场景:
 * - ✅ 无参、默认配置的全局单例(Effective Java 与 DCL 并列推荐)
 * - ✅ 不想在类加载主类时就创建实例,又要避免 DCL 手写错误
 * - ❌ 构造需要外部传参时 HOLDER 里无法灵活注入,应改用 DCL 或工厂 + DI
 *
 * Android 场景:
 * - ✅ 无 Context 或仅用 Application Context 的全局管理器(网络门面、缓存协调)
 * - ✅ 比 enum 更常出现在业务代码:懒加载、不抢 Application 启动时机
 * - 与 Hilt @Singleton 并存时,新代码优先 DI;Holder 适合无框架的 Java 模块
 * - 仍禁止持有 Activity Context,否则进程级单例导致泄漏
 *
 * 原理:
 * - 外部类加载不会初始化 Holder;第一次 getInstance() → 加载 Holder → new 一次
 *
 * 如何运行:
 * - javac -d out src/*.java
 * - java -cp out InnerClassSingleton
 *
 * 预期输出:
 * - 两次输出同一个对象引用,same instance = true
 */
public class InnerClassSingleton {
    private InnerClassSingleton() {
    }

    private static class Holder {
        private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
    }

    public static InnerClassSingleton getInstance() {
        return Holder.INSTANCE;
    }

    public static void main(String[] args) {
        InnerClassSingleton a = InnerClassSingleton.getInstance();
        InnerClassSingleton b = InnerClassSingleton.getInstance();
        System.out.println(a);
        System.out.println(b);
        System.out.println("same instance = " + (a == b));
    }
}