De methode equals() bepaalt of twee objecten "gelijk" zijn. Standaard vergelijkt het verwijzingen (d.w.z. ==), maar vaak vereisen klassen (zoals entiteiten, value-objecten) logische vergelijking op basis van gegevens.
Wanneer te overschrijven:
Vereisten:
Voorbeeld:
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); } }
Als twee objecten gelijk zijn volgens equals(), moet hun hashCode() dan altijd gelijk zijn?
Antwoord: Ja! Dit is een vereiste van de Java contracten. Maar het omgekeerde is niet waar: twee objecten met dezelfde hashCode kunnen ongelijk zijn volgens equals() — hashcodes kunnen samenvallen voor verschillende objecten (collisies).
Voorbeeld van een fout:
person1.equals(person2); // true person1.hashCode() != person2.hashCode(); // Fout!
Verhaal
In een bedrijfsapplicatie werd de entiteit Gebruiker in een HashSet geplaatst. Equals was overschreven, hashCode - niet. Na wijziging van velden die invloed hadden op equals, "verloor" de HashSet dit object: een zoekpoging met de methode contains gaf false terug, zelfs voor dezelfde gegevens.
Verhaal
In een IoT-project werden entiteiten tijdelijk alleen over id vergeleken, en daarna werd de logica veranderd naar equals met inachtneming van de naam. HashMap gedroeg zich onvoorspelbaar, bij het bijwerken van sleutels ontstonden duplicaten — het equals/hashCode contract werd geschonden door het mengen van implementatieversies.
Verhaal
Bij het schrijven van API voor het vergelijken van bestellingen, implementeerden twee verschillende klassen hun eigen equals; één riep getClass() aan, de andere instanceof. Dit leidde tot een niet-symmetrische vergelijking van bestellingen en bugs bij het gebruik van collecties en bedrijfslogica.