ProgrammingJava開発者

JavaにおけるhashCode()メソッドのオーバーライドのメカニズムはどのようになっていますか?その際に遵守すべき規則は何で、これらの規則を破った場合にどのような深刻なバグが発生する可能性がありますか?

Hintsage AIアシスタントで面接を突破

答え。

hashCode()メソッドのオーバーライドはequals()のオーバーライドと密接に関連しており、両方のメソッドがHashMap、HashSet、Hashtableなど、比較とハッシュ関数に基づくコレクションでのオブジェクトの正しい使用に必要な基盤を形成します。

規則:

  • equals()をオーバーライドする場合は、必ずhashCode()もオーバーライドしてください。
  • equals()が等しいオブジェクトは、同じhashCode()を返す必要があります。
  • エラーを回避するために、標準的なハッシュ生成方法(例:Objects.hash()やIDEテンプレート)を使用することをお勧めします。
  • hashCode()は同じオブジェクトに対してその「生涯」の間にわたって同じ値を返すべきです(hashCodeに参加するフィールドが不変である場合)。
class User { private String name; public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof User)) return false; User user = (User) o; return Objects.equals(name, user.name); } public int hashCode() { return Objects.hash(name); } }

引っ掛け問題。

質問: 「equals()が異なる二つのオブジェクトが同じhashCode()を返した場合、これはエラーになるのでしょうか?」

答え: いいえ、これはエラーではありません。ハッシュコードの衝突は解決可能で予想されるもので、重要なのはequalsで等しいオブジェクトが同じhashCodeを持つことです。equalsで異なるオブジェクトが同じhashCodeを持つ場合、コレクションは遅くなります(衝突が増えるため)が、正しく動作します。

知識不足から来る実際のエラーの例。


物語

財務ソフトウェアでは、プロジェクトを複数のフィールドで比較していますが、equals()だけをオーバーライドしました。HashSetにオブジェクトを格納していたため、hashCode()がオーバーライドされず、デフォルトで動作していたため、重複が発生しました。


物語

倉庫管理システムでは、ビジネスロジックの変更を追加した後、equals()を拡張しましたが、hashCode()を更新するのを忘れました。異なるhashCodeを持つがequals=trueのオブジェクトがHashMapで失われ(キーで見つからない)、大きな財務上のエラーを引き起こしました。


物語

ウェブアプリケーションでは、hashCodeの計算に可変フィールドを使用していました。内部フィールドの値が更新されるとハッシュが変更され、オブジェクトはHashSet/HashMapで「失われ」ました:標準的なメソッドで見つけたり削除したりすることができず、メモリリークやバグを引き起こしました。