什麼是單例模式 這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。 什麼是序列化 簡單來說序列化就是一種用來處理對象流的機制。所謂對象流也就是將 ...
什麼是單例模式
這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。
什麼是序列化
簡單來說序列化就是一種用來處理對象流的機制。所謂對象流也就是將對象的內容進行流化,流的概念這裡不用多說(就是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方法來返回我們指定好的對象了, 單例規則也就得到了保證。
如果喜歡此閱讀內容就點個推薦吧!
碼字不易,您的支持我對我最大的鼓勵。