请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

这里的加了枚举的单例模式是否有问题

先给出老师的饿汉式枚举封装的单例代码。

public class EnumStarvingSingleton {
    private EnumStarvingSingleton(){}

    public static EnumStarvingSingleton getInstance(){
        return ContainerHolder.HOLDER.instance;
    }

    private enum ContainerHolder{
        HOLDER;
        private EnumStarvingSingleton instance;
        ContainerHolder(){
            instance = new EnumStarvingSingleton();
        }
    }
}

再给出我的测试用例:

public class SingletonDemo {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Constructor constructor = EnumStarvingSingleton.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        EnumStarvingSingleton instance1 = (EnumStarvingSingleton) constructor.newInstance();
        EnumStarvingSingleton instance2 = EnumStarvingSingleton.getInstance();
        System.out.println(instance1 == instance2);
    }
}

我的测试用例结果是false,说明反射已经破坏了该单例模式。
一般用枚举类型抵御反射对单例的破坏,直接用枚举就行了,如下述代码所示:

public enum Singleton {
    INSTANCE
}

测试代码如下:

public class SingletonDemo {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Constructor constructor = Singleton.class.getDeclaredConstructor(String.class, int.class);
        constructor.setAccessible(true);
        Singleton instance1 = (Singleton) constructor.newInstance();
        Singleton instance2 = Singleton.INSTANCE;
        System.out.println(instance1 == instance2);
    }
}

上述测试会抛出IllegalArgumentException异常,因为枚举类无法通过反射来创建实例。
不知道为什么老师这里要多一层封装,把枚举作为私有的内部类来处理?

正在回答

1回答

翔仔 2020-03-26 18:12:04

同学好,你的这个变量名字好有迷惑性呀。。

        Constructor constructor = EnumStarvingSingleton.class.getDeclaredConstructor();
        EnumStarvingSingleton instance1 = (EnumStarvingSingleton) constructor.newInstance();

这个是EnumStarvingSingleton实例本身吧。。

EnumStarvingSingleton instance2 = EnumStarvingSingleton.getInstance();

EnumStarvingSingleton instance2 = EnumStarvingSingleton.getInstance(); 这个才是枚举的实例呢。。所以针对枚举的实例来讲,是单例的呀。

这里用内部枚举的原因主要就是通过内部枚举持有容器单例。保证持有的容器单例是不会被破坏的。。

0 回复 有任何疑惑可以回复我~
  • 提问者 慕数据4154996 #1
    非常感谢!
    回复 有任何疑惑可以回复我~ 2020-03-26 19:24:51
  • 提问者 慕数据4154996 #2
    那像我这样直接用enum定义单例不就可以了吗?为什么要像这样定义一个内部的枚举类啊?
    回复 有任何疑惑可以回复我~ 2020-03-26 19:26:04
  • 翔仔 回复 提问者 慕数据4154996 #3
    因为对外使用的时候得表现得像类一样,符合面向对象开发原则,里面有方法,有成员变量:)
    回复 有任何疑惑可以回复我~ 2020-03-27 01:19:22
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信