當單例模式遇到序列化會出現什么問題


什么是單例模式

  這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。

什么是序列化

  簡單來說序列化就是一種用來處理對象流的機制。所謂對象流也就是將對象的內容進行流化,流的概念這里不用多說(就是I/O)。我們可以對流化后的對象進行讀寫操作,也可將流化后的對象傳輸於網絡之間(注:要想將對象傳輸於網絡必須進行流化)!在對對象流進行讀寫操作時會引發一些問題,而序列化機制正是用來解決這些問題的!在Java里面,序列化需要實現Serializable接口。

問題分析

這里有一段演示代碼:

    public final class SingletonDemo implements Serializable {

        private SingletonDemo() { }

        private static final SingletonDemo INSTANCE = new SingletonDemo();

        public static SingletonDemo getInstance() { return INSTANCE; }

    }

  在這里簡單介紹一下,在SingletonDemo類中,有一個private修飾的構造器(該類不能再外部new創建,只能通過getInstance方法或者通過反射機制來獲得SingletonDemo,在SingletonDemo中已經創建好了一個私有的類對象(被private、static、final【不可修改,在創建時必須初始化】修飾)),這個類對象是由getinstance方法暴露給外界,是外界能夠獲得。這個類由自己創建對象,並且外部只能使用INSTANCE對象,符合單一,訪問對象的方式也唯一。所以這是一個經典的單例類。但是這個單例類實現了serializable接口,這個類可被序列化,可以寫到內存中,也可以通過反序列化拿到對象。

   一般來說, 一個類實現了 Serializable接口, 我們就可以把它往內存地寫再從內存里讀出而"組裝"成一個跟原來一模一樣的對象. 不過當序列化遇到單例時,這里邊就有了個問題: 從內存讀出而組裝的對象破壞了單例的規則. 單例是要求一個JVM中只有一個類對象的, 而現在通過反序列化,一個新的對象克隆了出來.

  當把 SingletonDemo對象(通過getInstance方法獲得的那個單例對象)序列化后再從內存中讀出時, 就有一個全新但跟原來不一樣的SingletonDemo對象存在了. 那怎么來維護單例模式呢?這就要用到readResolve方法了. 如下所示:

    public final class SingletonDemo implements Serializable{

        private SingletonDemo() { }

        private static final SingletonDemo INSTANCE = new SingletonDemo();

        public static SingletonDemo getInstance() { return INSTANCE; }

        private Object readResolve() throws ObjectStreamException {

           // instead of the object we're on,
           // return the class variable INSTANCE

          return INSTANCE;
       }
    }

  這樣當JVM從內存中反序列化地"組裝"一個新對象時,就會自動調用這個 readResolve方法來返回我們指定好的對象了, 單例規則也就得到了保證。
  如果喜歡此閱讀內容就點個推薦吧!
  碼字不易,您的支持我對我最大的鼓勵。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM