Java單例類與對象序列化
爲了保證全局只有一個實例,單例類往往將構造方法的訪問權限設置爲private:
public class Singleton implements Serializable{
private static final Singleton SINGLETON = new Singleton(100);
private int value;
private Singleton(int value) {
// private!
this.value = value;
}
public static Singleton getInstance() {
return SINGLETON;
}
}
對單例類進行序列化需要格外小心,下面看一段代碼:
public static void main(String[] args) throws IOException, ClassNotFoundException {
Singleton singleton1 = Singleton.getInstance();
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("singleton.dat"));
output.writeObject(singleton1);
ObjectInputStream input = new ObjectInputStream(new FileInputStream("singleton.dat"));
Singleton singleton2 = (Singleton) input.readObject();
System.out.println("創建新實例:" + (singleton1 != singleton2));
}
控制檯輸出:
創建新實例:true
上面代碼的運行結果表明,對單例類進行序列化可能會創建新的實例,即使構造方法是私有的!
爲了解決上述問題,需要定義一種被稱爲readResolve的特殊序列化方法。如果定義了readResolve方法,在對象序列化時就會調用它。
public class Singleton implements Serializable {
private static final Singleton SINGLETON = new Singleton(100);
private int value;
private Singleton(int value) {
// private!
this.value = value;
}
public static Singleton getInstance() {
return SINGLETON;
}
protected Object readResolve() throws ObjectStreamException {
return SINGLETON;
}
}
再次執行上面的測試代碼,控制檯輸出如下:
創建新實例:false