首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

《Effective Java》學習筆記(二):Object 通用方法正確覆寫 — equals、hashCode、toString、clone、compareTo

     編輯:Java 相關知識

前言

本文為《Effective Java》第 2 章讀書筆記,專講 java.lang.Object 非 final 方法的正確覆寫規範,是 Java 開發者必修的核心功夫。

第 7 條:覆寫 equals 遵守通用約定

五大約定:

  1. 自反性:x.equals(x) == true
  2. 對稱性:x.equals(y) == y.equals(x)
  3. 傳遞性:x.equals(y) && y.equals(z) → x.equals(z)
  4. 一致性:多次調用結果不變(前提對象未修改)。
  5. 非空性:x.equals(null) == false

易錯點: 對稱性與傳遞性在繼承中極易破壞。無法在擴展可實例化類並新增屬性的同時保持 equals 約定(除非放寬約定或使用組合)。

高質量 equals 處方:

  1. == 檢查同一引用。
  2. instanceof 檢查類型(或 getClass() == obj.getClass() 嚴格模式)。
  3. 轉型後比較「關鍵域」(業務唯一標識)。
  4. 驗證對稱、傳遞、一致。
  5. 覆寫 equals 必覆寫 hashCode。
  6. 勿過度聰明(如不區分大小寫比較字串),勿依賴不可靠資源(網路、DB)。
  7. 參數類型保持 Object,勿改為具體類(違反覆寫簽名)。

替代方案: 組合取代繼承,避開 equals 陷阱。

第 8 條:覆寫 equals 必覆寫 hashCode

否則無法在 HashMap/HashSet 等基於雜湊的集合中正常工作。理想雜湊函數將不等對象均勻分佈。

標準實現模板(Josh Bloch 配方):

@Override public int hashCode() {
    int result = 17; // 非零常數
    result = 31 * result + (boolField ? 1 : 0);
    result = 31 * result + intField;
    result = 31 * result + (int)(longField ^ (longField >>> 32));
    result = 31 * result + Float.floatToIntBits(floatField);
    long tmp = Double.doubleToLongBits(doubleField);
    result = 31 * result + (int)(tmp ^ (tmp >>> 32));
    result = 31 * result + (objField == null ? 0 : objField.hashCode());
    result = 31 * result + Arrays.hashCode(arrayField);
    return result;
}
  • 乘數 31 為質數,位移優化(31*i == (i<<5)-i)。
  • 必包含所有 equals 比較的關鍵域,勿為效能排除關鍵域。

第 9 條:總是覆寫 toString()

提供「自我描述」能力,便於除錯、日誌、UI 顯示。格式建議:ClassName[field1=value1, field2=value2]。若類含大量數據或敏感信息,可僅返回摘要。

第 10 條:謹慎覆寫 clone()

clone() 是另一構造器,實現深拷貝極其複雜且危險:

  • 實現 Cloneable(標記介面)。
  • 調用 super.clone() 獲取淺拷貝。
  • 手動深拷貝所有可變欄位(陣列、集合、可變物件)。
  • 處理 final 欄位無法修改的限制。

更好替代:拷貝構造器 / 拷貝工廠方法

public Yum(Yum source) { // 拷貝構造器
    this.field = source.field; // 不可變直接賦值
    this.mutableList = new ArrayList<>(source.mutableList); // 可變深拷貝
}
public static Yum newInstance(Yum source) { return new Yum(source); } // 工廠

優點:無拋出受檢異常、無需實現標記介面、類型安全、可轉換實現類型。

第 11 條:考慮實現 Comparable 接口

若類有自然順序(如數值、字串、日期),實現 Comparable<T>,滿足與 equals 一致的自反、對稱、傳遞、一致約定。配合 Collections.sort()、TreeSet/TreeMap、Arrays.sort() 等標準算法無縫協作。

總結

正確覆寫 Object 方法是專業 Java 開發者的分水嶺。遵循約定、使用標準模板、偏向拷貝構造器而非 clone、實現 Comparable 以賦能標準庫,能寫出健壯、高效、可維護的類。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved