文章目录
单例模式在序列化场景下实现
单例有懒汉,饿汉,双重锁,静态内部类,枚举类
单例的要求:构造私有,序列化反序列化唯一,线程实例唯一
一般的单例类尽管构造方法私有,但在序列化再反序列化时,会通过反射调用对象的构造方法,造成单例对象的不唯一
故而在序列化反序列化时,单例类必须提供一个方法readResolve 返回值为单例实例
code:
单例类:
public class Singleton implements Serializable {
private Singleton() {}
public static Singleton getInstance() {
return SingletonBuilder.INSTANCE;
}
/**
* 用于反序列化时保持单例唯一
*/
private Object readResolve() {
return SingletonBuilder.INSTANCE;
}
/**
* 静态内部类 延迟加载单例
*/
static class SingletonBuilder {
private static final Singleton INSTANCE = new Singleton();
}
}
psvm主方法:
ByteArrayOutputStream byteArrayOs = new ByteArrayOutputStream();
ObjectOutputStream objectOs = new ObjectOutputStream(byteArrayOs);
// 对象写入流中
objectOs.writeObject(Singleton.getInstance());
ObjectInputStream objectIs = new ObjectInputStream(new ByteArrayInputStream(byteArrayOs.toByteArray()));
// 从流中读取的对象对比静态内部类单例获取的对象
System.out.println(objectIs.readObject() == Singleton.getInstance());
执行结果:
true
Process finished with exit code 0
枚举单例无需readResolve 且不怕反射攻击
public enum EnumSingleton {
INSTANCE;
public EnumSingleton getInstance(){
return INSTANCE;
}
}