78條高質量編碼建議《Effective Java》(3~4)閱讀筆記(增加redis)

首先看看我們有哪些視頻資源(免費獲取全套):

78條高質量編碼建議《Effective Java》(3~4)閱讀筆記(增加redis)

接著上期繼續看本書高質量編碼建議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值,可以看到執行結果為:

78條高質量編碼建議《Effective Java》(3~4)閱讀筆記(增加redis)

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;

}

}

如此一來的執行結果為:

78條高質量編碼建議《Effective Java》(3~4)閱讀筆記(增加redis)

顯然此時被序列化過後還是單例,至於為什麼要實現readResolve,這個方法並不是Serializable接口的方法,在此我並沒有深究,究其原因估計是在反序列化的時候會調用這個奇怪的方法。

另外書中還提到了另外高檔的一種單例模式,此方法既能保證線程安全,也能保證被反序列化後還是單例。

78條高質量編碼建議《Effective Java》(3~4)閱讀筆記(增加redis)

可以看到它自帶序列化機制,且防止了多次實例化,非常高檔的一個單例實現。

4.通過私有構造器強化不可能實例的能力

在此條書中建議有的工具類例如Arrays等,對它們進行實例化並沒有意義,所以應該在它們的構造方法上應該使用private修飾

今天就這麼多了,明天持續更新,下期內容:

5.避免創建不必要的對象

6.消除過期對象的引用

78條高質量編碼建議《Effective Java》(3~4)閱讀筆記(增加redis)

看看我們的資料:

78條高質量編碼建議《Effective Java》(3~4)閱讀筆記(增加redis)

78條高質量編碼建議《Effective Java》(3~4)閱讀筆記(增加redis)

獲取方式:看文章尾部


想學習java,瞭解java,獲取java資源的歡迎進群:

java資源分享總群:238600498 ;java招聘信息共享群:489895481 ; Java高級架構師群:614527642

免費視頻資料獲取途徑:公眾平臺“java版web項目”(java_project)


分享到:


相關文章: