一个单例对象创建好之后,有时候需要将对象序列化然后进行数据持久化,下次使用的时候通过反序列化转化为内存对象。反序列化后的对象会重新分配内存,会破坏单例模式。
首先看支持序列化的单例类的代码:
// 实现Serializable即可实现序列化和反序列化
public class Singleton implements Serializable {
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
测试代码如下所示:
Singleton singleton = Singleton.getInstance();
Singleton singletonSerializable = null;
FileOutputStream fos = null;
try {
fos = new FileOutputStream("Singleton.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(singleton);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream("Singleton.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
singletonSerializable = (Singleton) ois.readObject();
ois.close();
System.out.println("比较原型对象与反序列化对象:"+(singleton == singletonSerializable));
} catch (Exception e) {
e.printStackTrace();
}
运行结果:
比较原型对象与反序列化对象:false |
可见单例模式会被反序列化破坏。
除了Java自带的反序列化方式以外,实际开发过程中更常见的是用FastJson或Moshi等开源框架将对象序列化成JSON或Protobuf,以下是测试Gson反序列化破坏单例的代码:
Gson gson = new Gson();
String json = gson.toJson(singleton);
singletonSerializable = gson.fromJson(json,Singleton.class);
System.out.println("比较原型对象与反序列化对象:"+(singleton == singletonSerializable));
运行结果:
比较原型对象与反序列化对象:false |
可见单例模式也会被JSON等其他格式的反序列化破坏,Jackson等其他框架同理。