首先看看我們有哪些視頻資源(免費獲取全套):
接著上期繼續看本書高質量編碼建議3、4條的閱讀筆記
3.用私有構造器或者枚舉類型強化singleton的屬性
書中的此條目下,我總結出來認為最有價值的是“能被序列化的線程安全的類,被序列化後是否還會是單例”。單例模式幾乎人人會寫,例如上面提到的勤加載(餓漢式)的單例模式:
public class Instance{
private static final Instance obj = new Instance();
//構造器私有隻能在類中實例化
private instance(){
}
public static Insatnce getInstance(){
return obj;
}
}
毫無疑問這個單例是線程安全的(上面對象實例化只能類內實例,通過靜態方法獲取),如果我們希望一個類能被序列化,那麼這個類直接實現Serializable就可以了,但是這樣能否保證被反序列化過後還是單例呢?
import java.io.Serializable;
/**
* 序列化單例對象
*/
public class Instance implements Serializable {
private static final Instance obj = new Instance();
private Instance() {
}
public static Instance getInstance() {
return obj;
}
}
測試代碼
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* 序列化與反序列化單例對象
* .
*/
public class Main {
public static void main(String[] args) throws Exception{
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("D:\\objFile.obj"));
Instance instance = Instance.getInstance();
out.writeObject(instance);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("D:\\objFile.obj"));
Instance instance1 = (Instance) in.readObject();
in = new ObjectInputStream(new FileInputStream("D:\\objFile.obj"));
Instance instance2 = (Instance) in.readObject();
System.out.println("obj1 hashcode:" + instance1.hashCode());
System.out.println("obj2 hashcode:" + instance2.hashCode());
in.close();
}
}
比較兩個實例對象的hash值,可以看到執行結果為:
hashcode哈希地址不一樣,就是不同的兩個對象
這就說明被反序列化過後便不再是單例。要保證單例還必須在單例類中實現readResolve的方法:
public class Instance implements Serializable {
private static final Instance obj = new Instance();
private Instance() {
}
public static Instance getInstance() {
return obj;
}
private Object readResolve(){
return obj;
}
}
如此一來的執行結果為:
顯然此時被序列化過後還是單例,至於為什麼要實現readResolve,這個方法並不是Serializable接口的方法,在此我並沒有深究,究其原因估計是在反序列化的時候會調用這個奇怪的方法。
另外書中還提到了另外高檔的一種單例模式,此方法既能保證線程安全,也能保證被反序列化後還是單例。
可以看到它自帶序列化機制,且防止了多次實例化,非常高檔的一個單例實現。
4.通過私有構造器強化不可能實例的能力
在此條書中建議有的工具類例如Arrays等,對它們進行實例化並沒有意義,所以應該在它們的構造方法上應該使用private修飾
今天就這麼多了,明天持續更新,下期內容:
5.避免創建不必要的對象
6.消除過期對象的引用
看看我們的資料:
獲取方式:看文章尾部
想學習java,瞭解java,獲取java資源的歡迎進群:
java資源分享總群:238600498 ;java招聘信息共享群:489895481 ; Java高級架構師群:614527642
免費視頻資料獲取途徑:公眾平臺“java版web項目”(java_project)
閱讀更多 JavaLeader 的文章