ProgrammazioneSviluppatore Java

Spiega le peculiarità del metodo equals() in Java: quando e perché sovrascriverlo, come implementarlo correttamente e quali problemi possono sorgere se non viene utilizzato correttamente.

Supera i colloqui con l'assistente IA Hintsage

Risposta

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:

  • Se per la tua classe è importante l'identità logica degli oggetti (ad esempio, due utenti con la stessa email sono "lo stesso utente")
  • Se l'oggetto sarà memorizzato in collezioni (ad esempio, HashSet), che utilizzano equals (e hashCode)

Requisiti:

  • Equals deve essere reflexive, symmetric, transitive, consistent e per qualsiasi x non-null, x.equals(null) deve essere false
  • Quando sovrascrivi equals, devi OBBLIGATORIAMENTE sovrascrivere hashCode!

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

Domanda trabocchetto

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!

Esempi di errori reali a causa della mancanza di conoscenza delle sottigliezze dell'argomento


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.