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:
如下所示:
Java代碼
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()方法:
Java代碼
//readResolve 方法維持瞭Singleton的單例屬性
private Object readResolve() throws ObjectStreamException{
return uniqueInstance;
}
再進行測試:輸出結果為true
反序列化之後新創建的對象會先調用此方法,該方法返回的對象引用被返回,取代瞭新創建的對象。本質上,該方法忽略瞭新建對象,仍然返回類初始化時創建的那個實例。