ProgrammierungJava Entwickler

Wie funktioniert der Mechanismus der Überschreibung der Methode hashCode() in Java, welche Regeln müssen dabei beachtet werden und zu welchen kritischen Bugs kann ein Verstoß gegen diese Regeln führen?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

Die Überschreibung der Methode hashCode() steht in engem Zusammenhang mit der Überschreibung von equals(): Beide Methoden bilden die Basis für die korrekte Verwendung von Objekten in Sammlungen wie HashMap, HashSet, Hashtable und anderen Strukturen, die auf Vergleichen und Hash-Funktionen basieren.

Regeln:

  • Wenn Sie equals() überschreiben, müssen Sie auch hashCode() unbedingt überschreiben.
  • Objekte, die nach equals() gleich sind, sollten denselben hashCode() zurückgeben.
  • Es wird empfohlen, standardmäßige Methoden zur Hashgenerierung zu verwenden, z.B. Objects.hash() oder IDE-Vorlagen, um Fehler zu vermeiden.
  • hashCode() sollte für dasselbe Objekt über dessen "Lebensdauer" hinweg denselben Wert zurückgeben (vorausgesetzt, die für hashCode verwendeten Felder sind unveränderlich).
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); } }

Zwickende Frage.

Frage: "Was passiert, wenn zwei verschiedene Objekte, die nach equals() ungleich sind, denselben hashCode() zurückgeben? Wird das ein Fehler sein?"

Antwort: Nein, das ist kein Fehler. Hashcode-Kollisionen sind lösbar und zu erwarten – wichtig ist nur, dass, wenn Objekte nach equals gleich sind, ihr hashCode auch gleich ist. Wenn verschiedene Objekte nach equals ungleich sind, aber denselben hashCode liefern, arbeiten die Sammlungen langsamer (aufgrund einer höheren Anzahl von Kollisionen), aber korrekt.

Beispiele für reale Fehler aufgrund mangelnden Wissens über die Feinheiten des Themas.


Geschichte

In einer Finanzsoftware wurden Projekte anhand mehrerer Felder verglichen, aber nur equals() überschrieben. Objekte wurden in HashSet gespeichert, und es entstanden Duplikate, da hashCode() nicht überschrieben wurde und standardmäßig arbeitete (jeder Instanz unterschiedlich war).


Geschichte

In einem Lagerverwaltungssystem wurde nach der Änderung der Geschäftslogik equals() erweitert, aber hashCode() wurde vergessen zu aktualisieren. Objekte mit unterschiedlichen hashCode, aber equals=true, gingen in HashMap verloren (waren nicht über den Schlüssel auffindbar), was zu erheblichen finanziellen Fehlern führte.


Geschichte

In einer Webanwendung wurden veränderbare Felder zur Berechnung von hashCode verwendet. Bei der Aktualisierung des Wertes eines internen Feldes änderte sich der Hash, und das Objekt "ging verloren" für HashSet/HashMap: es war unmöglich, es über die Standardmethoden zu finden oder zu löschen, was zu Speicherlecks und Bugs führte.