史上最牛的单例

来源于书籍:Spring5核心原理与30个类手写实战

使用静态内部类实现的单例模式,利用了JVM的运行机制,外部类初始化的时候并不会初始化静态的内部类,只有在使用到了内部类的时候才会去初始化他,然后就会使单例对象初始化,这种方式是Effective Java中比较推荐的一种方式。

问题在于,反射能破坏这种单例模式,因为反射能调用其构造函数创建一个新的对象,那么怎么办?就需要在构造函数上进行处理了,就得到了书上这样的方式

public class StaticInnerObjectSingleton {
    private StaticInnerObjectSingleton() {
        if (LazyHolder.SINGLETON != null) {
            throw new IllegalStateException("不允许创建多个实例");
        }
    }

    public static StaticInnerObjectSingleton getInstance() {
        return LazyHolder.SINGLETON;
    }

    private static class LazyHolder {
        static final StaticInnerObjectSingleton SINGLETON = new StaticInnerObjectSingleton();
    }
}

为什么要判断为空?而不是直接抛出异常。因为自己第一次初始化的时候还需要去调用此方法,所以当然不能直接抛出异常。
如果反射调用构造函数,执行到if的时候就会导致静态内部类的初始化,然后在初始化的过程中会导致静态内部类里面的静态代码块执行,然后静态代码快又会调用构造函数,这个时候其内部的SINGLETON肯定是空,所以能初始化成功,初始化成功之后SINGLETON就不为空了,就导致执行失败,成功避免了反射的破坏单例

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值