Die Methode equals() bestimmt, ob zwei Objekte "gleich" sind. Standardmäßig vergleicht sie die Referenzen (d.h. ==), aber häufig erfordern Klassen (z.B. Entitäten, Value-Objekte) einen logischen Vergleich basierend auf Daten.
Wann überschreiben:
Anforderungen:
Beispiel:
public class Person { private String email; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(email, person.email); } @Override public int hashCode() { return Objects.hash(email); } }
Wenn zwei Objekte gleich sind laut equals(), muss ihr hashCode() immer gleich sein?
Antwort: Ja! Das ist eine Anforderung der Java-Verträge. Aber umgekehrt ist es nicht wahr: Zwei Objekte mit demselben hashCode können ungleich nach equals() sein – Hashcodes können für unterschiedliche Objekte kollidieren.
Beispiel für einen Fehler:
person1.equals(person2); // true person1.hashCode() != person2.hashCode(); // Fehler!
Geschichte
In einer Unternehmensanwendung wurde die Benutzerentität in HashSet eingefügt. Equals wurde überschrieben, hashCode jedoch nicht. Nach der Änderung von Feldern, die equals beeinflussen, "verlor" HashSet dieses Objekt: Der Versuch, die Methode contains zu verwenden, gab false zurück, selbst bei denselben Daten.
Geschichte
In einem IoT-Projekt wurden Entitäten vorübergehend nur nach ID verglichen, und dann wurde die Logik auf equals unter Berücksichtigung des Namens geändert. HashMap verhielt sich unvorhersehbar, bei der Aktualisierung von Schlüsseln entstanden Duplikate – der equals/hashCode-Vertrag wurde durch Vermischung der Implementierungsversionen verletzt.
Geschichte
Bei der Erstellung einer API zur Vergleich von Bestellungen implementierten zwei verschiedene Klassen ihr eigenes equals, eine davon verwendete getClass(), die andere instanceof. Dies führte zu asymmetrischen Vergleichen von Bestellungen und zu Bugs bei der Verwendung von Sammlungen und Geschäftsanwendungen.