文章目录
1. 前言
单例模式我们大家都知道,但是,单例模式也是可以被破坏的。下面介绍单例的破坏与预防。
单例的破坏我所了解的主要有两种情况:
- 主要是利用反射来调用你私有化的构造方法来创建对象
- 利用序列化来破坏
2. 反射破坏情况
反射破坏主要是调用你私有化的构造方法来创建对象。
2.1 原始代码
package pers.lzy.singleton.hungry;
import java.io.Serializable;
public class SingleTon implements Serializable {
// 构造方法私有化
private SingleTon() {
}
// 初始化对象
private final static SingleTon INSTANCE = new SingleTon();
// 设置获取对象方法
public static SingleTon getInstance () {
return INSTANCE;
}
}
2.2 破坏代码
你不是构造方法私有化了嘛?不给我调用,那我就反射强制调用。如下图
2.3 解决办法
既然你强制调用了我的构造方法,那我就再构造方法里面做文章。
思路:你调用我构造方法,我发现我已经创建过了,我就给你抛出异常,不让你反射调用。代码如下:
3. 序列化破环情况
序列化破坏的思路,就是将对象序列化,之后呢,在反序列化成为对象。这样反序列化的对象可能就是另一个对象了。此举将破坏单例
3.2 破环代码
3.3 解决办法
再单例类中写一个readResolve方法
3.4 jdk源码分析
你会好奇为什么写这么一个方法,就可以解决这个问题呢?跟踪一下jdk源码可知。如下图
4. 个人建议
个人建议,使用单例模式尽量使用枚举来实现。
4.1 为何要使用枚举实现单例?
观看源码 + 反编译可知,jdk在底层已经帮我们进行判断,所以枚举实现的单例是不可能被反射与序列化破坏的。那么jdk帮我们做的事儿,他能不靠谱?所以有大牛推荐此方式来实现单例。
枚举实现的单例是饿汉式的。
5. 总结
随便看看吧,也没什么东西,加油。