EnumStarvingSingleton实例还是可以创建新的实例
来源:5-6 无视反射和序列化攻击的单例
![](http://img1.sycdn.imooc.com/user/5495aee30001d58607380740-100-100.jpg)
hellocp7
2020-07-02
老师你好,我发现你在测试之前编写的恶汉和懒汉单例时,在SimpleDemo里面都是直接打印了constructor.newInstance()的结果,也就是
System.out.println(StarvingSingleton.getInstance());
Class clazz = StarvingSingleton.class;
Constructor constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
System.out.println(constructor.newInstance());
output:
com.imooc.demo.pattern.singleton.StarvingSingleton@e580929
com.imooc.demo.pattern.singleton.StarvingSingleton@1cd072a9
这里的结果确实如你所说两个打印的结果不一样,说明这个StarvingSingleton的实例并不唯一。但是当你测试EnumStarvingSingleton的时候你是又强制转成了EnumStarvingSingleton,然后调用了getInstance()方法
System.out.println(StarvingSingleton.getInstance());
EnumStarvingSingleton enumStarvingSingleton = (EnumStarvingSingleton)constructor.newInstance();
System.out.println(enumStarvingSingleton.getInstance());
output:
com.imooc.demo.pattern.singleton.EnumStarvingSingleton@1cd072a9
com.imooc.demo.pattern.singleton.EnumStarvingSingleton@1cd072a9
这里的结果也确实显示两个实例是同一个。
但是如果我在测试EnumStarvingSingleton的时候不用getInstance()方法,而是直接像你第一次测试的时候直接调用constructor.newInstance(),好像输出的结果还是非同一个实例。这样我还可以创建新的EnumStarvingSingleton实例,而非第一次创建的那个,那这个单例还有意义么?
另外我尝试把你第一次测试StarvingSingleton时用反射创建的实例强制转成StarvingSingleton,然后调用getInstance()方法,具体如下
System.out.println(StarvingSingleton.getInstance());
Class clazz = StarvingSingleton.class;
Constructor constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
StarvingSingleton starvingSingleton = (StarvingSingleton)constructor.newInstance();
System.out.println(starvingSingleton.getInstance());
output:
com.imooc.demo.pattern.singleton.StarvingSingleton@e580929
com.imooc.demo.pattern.singleton.StarvingSingleton@e580929
结果还是相同的,所以我就有些疑惑是不是只要调用getInstance()方法我们就能保证是同一个实例了?
可能写的有点多,过于复杂,希望老师谅解。谢谢。
4回答
-
谷杨
2022-03-16
同学理解了么,我刚看到这里,也有同样的疑惑。如果都调用getInstance()方法,就都是同一个实例啊,跟枚举的单例有何区别呢?
00 -
笑看从前小菜哥
2020-08-28
小小的脑袋大大的问号,这种方式好像也避免不了反射的入侵,依然能创建新的实例
012020-08-28 -
翔仔
2020-07-05
public static BeanContainer getInstance() { return ContainerHolder.HOLDER.instance; }
同学你调用的是这个呀,所以还是使用的内部属性。。
00 -
翔仔
2020-07-03
同学好,其实我们主要是为了保证
EnumStarvingSingleton
里面的那个枚举类型的成员变量是单例就可以了,外层是的
EnumStarvingSingleton
是没办法保证单例的,但是它的成员变量可以,而且也改不了
072022-03-16
相似问题