有什么方法能够阻止反射对单例模式对破坏

2019-11-08 10:10:19 +08:00
 hHarvey

判断成员变量的话,反射也能修改这个变量的值啊。。

2767 次点击
所在节点    程序员
12 条回复
HongJay
2019-11-08 10:11:50 +08:00
```
十、枚举

public enum Singleton {
INSTANCE
}

枚举类单例模式是《 Effective Java 》作者 Josh Bloch 极力推荐的单例方法

借助 JDK 1.5 中添加的枚举来实现单例模式。P.S. Enum 是没有 clone()方法的

1. 枚举类类型是 final 的「不可以被继承」
2. 构造方法是私有的「也只能私有,不允许被外部实例化,符合单例」
3. 类变量是静态的
4. 没有延时初始化,随着类的初始化就初始化了「从上面静态代码块中可以看出」
5. 由 4 可以知道枚举也是线程安全的

优点:写法简单,不仅能避免多线程同步问题,而且还能防止反序列化、反射、克隆重新创建新的对象。
缺点:JDK 1.5 之后才能使用。
```
softtwilight
2019-11-08 10:19:16 +08:00
1 楼正解,不过有一个疑问,有必要防止反射创建单例吗,哪些场景有用?
wysnylc
2019-11-08 10:25:50 +08:00
枚举写单例只有一个坏处,麻烦
hHarvey
2019-11-08 10:40:19 +08:00
@HongJay 嗯嗯,之前没清楚枚举写单例的意思,自己枚举里又维护了一个类
lihongming
2019-11-08 10:44:26 +08:00
设计模式本是用于解决一类问题的通用方法,可这么搞就成了利用某一特定语言的特性(有时甚至是 BUG )来强行实现,违背了设计模式的本意。

另外用反射来破坏你模式的那些人,肯定是有特殊需要的,有必要封那么死么?只要防止被人非本意的破坏就好。
Mutoo
2019-11-08 10:52:19 +08:00
设计模式是一种设计共识,不是一种防御手段。
hHarvey
2019-11-08 11:05:40 +08:00
但是用枚举实现单例,这个单例的属性值并不能序列化啊
momocraft
2019-11-08 11:10:36 +08:00
在 constructor 执行时 如果已有 instance 就 java.lang.System.exit(1)

然后等人提 bug
Raymon111111
2019-11-08 11:36:06 +08:00
用枚举

官方推荐
loshine1992
2019-11-08 11:44:46 +08:00
@lihongming

设计模式是总结出来的最佳实践

Java 里用枚举实现单例就是绝大多数情况下最佳实践
ysweics
2019-11-08 13:02:09 +08:00
如果没有开始写,那就用枚举实现,如果已经是老项目里面,可以在构造方法里面加上限制,方案就是 8 楼给出的方案,当然既然有反射破坏,那你反序列破坏也要考虑到
cco
2019-11-08 17:29:10 +08:00
想想谁没事去破坏你的单例?了解其思想即可,想那么多干嘛

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/617476

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX