1. 用靜態方法替代構造器(五個優點、兩個缺點)。
相比于構造器,優點如下:
- 有名稱;
- 不用再每次調用時返回一個新的對象;
- 可以返回聲明類型的子類型的對象;適用于基于接口的框架;
- 每次調用時,可以基于不同的參數返回不同的對象實例;
- 所返回對象的類并不一定要存在;這種靈活的靜態工廠方法提供了靈活的服務提供者框架;
相比于構造器,缺點如下: - 如果沒有公共的或者受保護的構造器,就不能為其生成子類;
子類構造器會自動調用父類構造器,所以當父類沒有構造器為其調用時,就沒有辦法創建子類;
- JavaDoc生成文檔時,對其展示沒有構造器明顯;
2. 當構造函數的參數比較多時使用生成器。
- Builder類作為使用類的靜態內部類,其字段為外部類可能需要的構造參數;
- 可以防止復雜對象在構造過程中被破壞;
- 同一個生成器可以用來生成多個相同的對象(享元);
3. 利用私有構造器或者枚舉類型強化Singleton屬性;
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() {...}
// ...
// 第二種
private static final Elvis INSTANCE = new Elvis();
public static Elvis getInstance () { return INSTANCE; }
// 此處的作用:防止Singleton的對象序列化后,再反序列化會生成新的對象,
// 破壞了Singleton的設計;
private Object readResolve() {
return INSTANCE; // 讓GC處理假的Elvis對象;
}
}
4. 利用私有構造器防止類被實例化;(上面??的代碼有示例)
5. 優先考慮通過依賴注入來鏈接資源;
對于行為會被底層資源以參數化的方式影響的類而言,靜態工具類和Singleton類都不合適;
// 依賴注入:即將依賴資源通過參數的形式傳遞到類的構造器中
public class SpellChecker {
private final Lexicon dictionary;
public SpellChecker(Lexicon dictionary) {
this.dictionary = Object.requiredNonNull(dictionary);
}
}
6. 避免創建不必要的對象;
- 比如正則處理會生成Pattern對象,對性能要求高的場景,可以預先生成Pattern對象;
- 自動裝箱也會生成可能不必要的對象;所以優先使用基本類型而不是其封裝類,并提防無意中的自動裝箱;
7. 及時清理掉過期的引用;
8. 承接上一點,避免使用終結(finalizer)方法和清理(cleaner)方法;
- 兩個方法清理不夠及時,甚至不保證會運行;
- 終結過程中發生的異常會被忽略,導致其他對象可能處于損壞狀態;
9. 與try-finally相比,首選try-with-resources;
10. 重寫equals方法;
需要遵守五個約定:
-
自反性
:x.equals(x); -
對稱性
:x.equals(y) 與 y.equals(x)結果相同; -
傳遞性
:x.equals(y) && y.equals(z) => x.equals(z); -
一致性
: 無論何時調用,x.equals(y)的結果不變; -
非空性
:x.equlas(null) 返回false;
編寫高質量equals方法的技巧: - 使用
==
檢查參數是否指向當前對象的引用; - 使用 instanceof 運算符檢查參數是否具有正確的類型;
- 將參數轉換為正確的類型;
- 對于類中每個“重要”的字段,檢查參數的這些字段是否與當前對象相應字段匹配;
11. 重寫equals方法時應始終重寫hashcode方法;
- equals相等,hashcode一定相等;
- hashcode相等,equals不一定相等;
- hash算法應盡可能返回分散的散列值,以避免hash沖突,導致檢索性能較低;
12. 總是重寫toString() 方法;
- 可以增強debug或者日志中類的可讀性;
13. 謹慎重寫clone方法;
- clone的實現可能會是一個淺拷貝;
- clone充當了構造器的作用,必須確保它不會對原始對象造成傷害,并確保它在克隆體上正確建立不變式;
- 大多數情況,提供復制構造器會是更好的選擇;
public class Yum {
public Yum(Yum yum) {
// ...
}
}
14. 考慮實現Comparable接口;
- 當類可能需要一些比較操作時可考慮實現;
- 盡量使用系統提供的基于靜態的比較器,或者基于比較器構造方法的比較器;
// 基于靜態的比較器
static Comparator<Object> hashCodeOrder = new Comparator<>() {
public int compare(Object o1, Object o2) {
return Integer.compare(o1.hashCode(), o2.hashCode());
}
}
// 基于比較器構造方法
static Comparator<Object> hashCodeOrder = Comparator.compareInt(o -> o.hashCode());