Java單例類與對象序列化

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章