Il metodo equals() determina se due oggetti sono "uguali". Di default confronta i riferimenti (cioè ==), ma spesso le classi (ad esempio, entità, oggetti valore) richiedono un confronto logico basato sui dati.
Quando sovrascrivere:
Requisiti:
Esempio:
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); } }
Se due oggetti sono uguali secondo equals(), il loro hashCode() deve sempre essere lo stesso?
Risposta: Sì! Questo è un requisito dei contratti Java. Ma l'inverso non è vero: due oggetti con lo stesso hashCode possono non essere uguali secondo equals() — gli hashCode possono coincidere per oggetti diversi (collisioni).
Esempio di errore:
person1.equals(person2); // true person1.hashCode() != person2.hashCode(); // Errore!
Storia
In un'applicazione aziendale, l'entità Utente è stata inserita in HashSet. Equals è stato sovrascritto, hashCode — no. Dopo la modifica dei campi che influenzano equals, HashSet ha "perso" questo oggetto: il tentativo di ricerca con il metodo contains restituiva false, anche per gli stessi dati.
Storia
In un progetto IoT, le entità sono state temporaneamente confrontate solo per id, mentre poi la logica è stata cambiata in equals tenendo conto del nome. HashMap ha iniziato a comportarsi in modo imprevedibile, durante l'aggiornamento delle chiavi si sono verificati duplicati — il contratto equals/hashCode è stato violato a causa della mescolanza delle versioni di implementazione.
Storia
Scrivendo un'API per il confronto degli ordini, due classi diverse implementavano il proprio equals, una delle quali chiamava getClass(), l'altra instanceof. Questo ha portato a confronti asimmetrici degli ordini e a bug nell'uso delle collezioni e della logica aziendale.