Java静态内部类单例案例怎么写

wen java案例 27

本文目录导读:

Java静态内部类单例案例怎么写

  1. 标准写法
  2. 客户端测试代码
  3. 进阶:带参数的单例
  4. 为什么这种方式是线程安全的?
  5. 对比其他单例模式

Java 静态内部类实现单例模式是线程安全且延迟加载的经典做法,它利用了 Java 类加载机制(类加载时才会初始化静态内部类)和 final 字段的线程安全性。

以下是具体的案例代码及详细解释:

标准写法

public class Singleton {
    // 1. 私有化构造方法,防止外部直接 new
    private Singleton() {
        // 可以在这里做一些初始化操作
        System.out.println("Singleton 实例被创建");
    }
    // 2. 公有的静态获取实例方法
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
    // 3. 静态内部类(核心)
    //    只有当 getInstance() 方法被调用时,此类才会被 JVM 加载
    private static class SingletonHolder {
        // 4. 在静态内部类中持有外部类的唯一实例
        //    该变量在类加载时被初始化,且由 JVM 保证线程安全性
        private static final Singleton INSTANCE = new Singleton();
    }
    // 为了演示效果,添加一个业务方法
    public void doSomething() {
        System.out.println("执行单例对象的方法");
    }
}

客户端测试代码

public class Main {
    public static void main(String[] args) {
        // 验证是否为同一个对象
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println("instance1 == instance2: " + (instance1 == instance2)); // 输出 true
        // 测试方法调用
        instance1.doSomething();
    }
}

进阶:带参数的单例

单例通常是无状态的,但有时需要传递配置参数,静态内部类也可以支持:

public class ConfigSingleton {
    private final String value;
    // 私有构造方法带参数
    private ConfigSingleton(String value) {
        this.value = value;
    }
    public static ConfigSingleton getInstance(String configValue) {
        // 避免在第一次 getInstance() 时传入不同的值
        return SingletonHolder.INSTANCE;
    }
    // 注意:这种方式第一次初始化后,参数就固定了
    public String getValue() {
        return value;
    }
    private static class SingletonHolder {
        // 需要你预先知道默认值,或者通过某种方式设置
        private static final ConfigSingleton INSTANCE = new ConfigSingleton("defaultConfig");
    }
}

为什么这种方式是线程安全的?

  1. 类加载机制SingletonHolder 是一个内部类,只有在 getInstance() 方法被第一次调用时,JVM 才会加载 SingletonHolder 类。
  2. 初始化锁:JVM 在类加载期间会获取一个初始化锁,保证类的 <clinit>() 方法(包含静态字段初始化和静态代码块)只会被一个线程执行一次
  3. final 关键字INSTANCEstatic final 修饰,保证了可见性和不可变性,所有线程看到的一定是初始化完全的对象。

对比其他单例模式

特点 饿汉式 懒汉式(DCL双重检查锁定) 静态内部类
延迟加载 ❌ (类加载时就创建)
线程安全 ✅ (需小心实现) ✅ (最简洁安全)
实现复杂度 中(需用 volatile + synchronized)
可能的问题 浪费内存 代码易出错 无法传参(初始化后)
  • 优点:代码清晰,性能高,无锁开销,线程绝对安全。
  • 适用场景:大多数需要延迟加载的单例场景。
  • 最佳实践:不需要考虑参数传递的通用单例,推荐直接使用这种写法。

抱歉,评论功能暂时关闭!