首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java HashMap 死循環根因:hashCode() 遞歸調用自身導致棧溢出

     編輯:程式設計綜合問答

問題代碼

public int hashCode() {
    System.out.println(this.name + ".....hashCode");
    return this.hashCode() + this.age * 7; // 遞歸調用自身!
}

錯誤分析

this.hashCode() 在方法內部調用了**自身**,導致無限遞歸,最終 StackOverflowError(表現為程序卡死/死循環)。

正確實現

@Override
public int hashCode() {
    int result = name != null ? name.hashCode() : 0;
    result = 31 * result + age;
    return result;
}

// 或使用 Objects.hash (Java 7+)
@Override
public int hashCode() {
    return Objects.hash(name, age);
}

equals() 規約同步檢查

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (!(obj instanceof Person)) return false;
    Person other = (Person) obj;
    return age == other.age && Objects.equals(name, other.name);
}

核心原則:equals 相等的對象,hashCode 必須相等。以上實現滿足該契約。

為什麼會寫出遞歸代碼?

  • 誤以為 this.hashCode() 會調用父類 Object.hashCode()(返回對象地址哈希)。實際上 this.hashCode() 解析為**當前類重寫後的方法**,形成遞歸。
  • 想獲取對象身份哈希碼應用 System.identityHashCode(this),但極少用於業務 hashCode 實現。

HashSet/HashMap 存放自定義對象完整清單

  1. 重寫 equals() 和 hashCode(),保持一致性。
  2. 字段最好為 final(不可變對象),避免放入集合後修改字段導致哈希值改變、無法查找/刪除。
  3. 若繼承鏈中父類已重寫,子類應調用 super.hashCode() 組合。

總結

hashCode() 方法中調用 this.hashCode() 導致無限遞歸死循環。修正為基於業務字段(name、age)計算哈希值,配合 equals() 正確重寫,即可正常用於 HashSet/HashMap。

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