ProgrammierungJava Entwickler

Erklären Sie die Besonderheiten der Methode equals() in Java: wann und warum sie überschrieben werden sollte, wie sie richtig implementiert wird und welche Probleme bei falscher Verwendung auftreten können.

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

Antwort

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:

  • Wenn die logische Identität von Objekten für Ihre Klasse wichtig ist (z.B. zwei Benutzer mit derselben E-Mail sind "der gleiche Benutzer")
  • Wenn das Objekt in Sammlungen gespeichert wird (z.B. HashSet), die equals (und hashCode) verwenden

Anforderungen:

  • Equals muss reflexiv, symmetrisch, transitiv, konsistent sein und für jedes nicht-null x, x.equals(null) muss false sein
  • Bei der Überschreibung von equals muss unbedingt auch hashCode überschrieben werden!

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); } }

Fangfrage

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!

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


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.