Sington类的序列化
为了使Singleton类变成可序列化的(serializable),仅仅实现Serializable接口是不够的。为了维护 Singleton的单例性,你必须给Singleton类提供一个readResolve方法,否则的话,一个序列化的实例,每次反序列化的时候都会产 生一个新的实例。Singleton 也不会例外。
through the serializable tools, someone can write a singleton instance to disk, and then read it back up, effectively getting a new instance. Even though the constructor is private, the serializable tools have special access to create instances of a class regardless. Serialization has a special hook it uses - a private method on the class being instantiated calledreadResolve()
- which is meant to supply a 'hook' for a class developer to ensure that they have a say in what object is returned by serialization. Oddly enough, readResolve()
is not static, but is instead invoked on the new instance just created by the serialization. We'll get into that in a minute - for now, here is how our readResolve()
method works with our singleton:
如下所示:
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
- import java.io.ObjectStreamException;
- import java.io.Serializable;
- //Singleton with final field
- public class Singleton implements Serializable{
- private static final long serialVersionUID = 5765648836796281035L;
- public static final Singleton uniqueInstance = new Singleton();
- private Singleton(){
- }
- //...Remainder omitted
- public static void main(String[] args) throws Exception{
- //序列化
- ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\Singleton.obj"));
- Singleton singleton = Singleton.uniqueInstance;
- objectOutputStream.writeObject(singleton);
- objectOutputStream.close();
- //反序列化
- ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\Singleton.obj"));
- Singleton singleton2 = (Singleton)objectInputStream.readObject();
- objectInputStream.close();
- //比较是否原来的实例
- System.out.println(singleton==singleton2);
- }
- }
输出结果为:false
解决方法是为Singleton类增加readResolve()方法:
- //readResolve 方法维持了Singleton的单例属性
- private Object readResolve() throws ObjectStreamException{
- return uniqueInstance;
- }
再进行测试:输出结果为true
反序列化之后新创建的对象会先调用此方法,该方法返回的对象引用被返回,取代了新创建的对象。本质上,该方法忽略了新建对象,仍然返回类初始化时创建的那个实例。