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

Java 高品質 equals() 實作指南:規約、陷阱與最佳模式

     編輯:關於.NET

什麼是 equals()

Object.equals(Object) 用於判斷兩個物件是否「邏輯相等」。預設實作比較參考位址 (this == obj),子類別需覆寫以實現值語意。

equals() 規約 (JLS 必須滿足)

  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
違反規約會導致 HashMap、HashSet、ArrayList.contains() 等集合行為錯誤。

高品質實作 5 步驟

1. 使用 instanceof 檢查型別

if (!(obj instanceof MyClass)) return false;

支援子類別多態比較;若需嚴格同類別可用 getClass() != obj.getClass()。

2. 轉型並比較關鍵欄位

MyClass other = (MyClass) obj;
return this.id == other.id 
    && Objects.equals(this.name, other.name)
    && Double.compare(this.score, other.score) == 0;
  • 基本型別用 == (float/double 用 Float.compare/Double.compare 處理 NaN)。
  • 物件參考用 Objects.equals(a, b) (Null-safe)。
  • 陣列用 Arrays.equals 或 Arrays.deepEquals。

3. 覆寫 hashCode() 保持一致性

@Override
public int hashCode() {
    return Objects.hash(id, name, score);
}

鐵律:a.equals(b) → a.hashCode() == b.hashCode()。反之不必然。

4. 別忘了 @Override 註解

編譯器會檢查簽名是否正確覆寫,防止拼字錯誤變成多載。

5. 考慮效能:先比較廉價/高區辨度欄位

如 id 為主鍵,優先比較 id,不相等直接返回,避免昂貴字串比較。

完整範例

public final class User {
    private final long id;
    private final String name;
    private final double score;

    public User(long id, String name, double score) {
        this.id = id;
        this.name = name;
        this.score = score;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof User)) return false;
        User other = (User) obj;
        return id == other.id
            && Objects.equals(name, other.name)
            && Double.compare(score, other.score) == 0;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, score);
    }
}

常見錯誤

錯誤後果
只覆寫 equals 不覆寫 hashCode放入 HashMap/HashSet 找不到、重複
參數型別寫成 MyClass 而非 Object變成多載,集合仍呼叫 Object.equals
使用 getClass() 破壞對稱性子類別實例與父類別實例比較失效
比較可變欄位物件放入 Set 後修改欄位導致找不到
float/double 直接 == 比較NaN、-0.0 語意錯誤

工具支援

  • IDE 自動產生 (Alt+Insert → equals/hashCode)。
  • Lombok @EqualsAndHashCode 註解自動實作。
  • Google AutoValue / Immutables 產生不可變值類別。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved