Sobes.tech
Middle

Come sovrascrivere correttamente il metodo equals in Java?

sobes.tech AI

Risposta dell'AI

// Esempio di ridefinizione minima corretta di equals
class MyClass {
    private int id;
    private String name;

    public MyClass(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override // Annotazione obbligatoria
    public boolean equals(Object o) {
        // 1. Controllo di identità
        if (this == o) return true;
        // 2. Controllo di null e corrispondenza delle classi
        // Usare getClass() per un controllo rigoroso
        if (o == null || getClass() != o.getClass()) return false;
        // 3. Cast
        MyClass myClass = (MyClass) o;
        // 4. Confronto dei campi significativi
        return id == myClass.id &&
               // Usare Objects.equals per confrontare gli oggetti (gestisce null)
               Objects.equals(name, myClass.name);
    }
}

Regole per una corretta ridefinizione di equals (secondo il contratto di Object.equals):

  • Riflessività: Per ogni valore non nullo x, x.equals(x) deve restituire true.
  • Simmetria: Per ogni x e y non nulli, x.equals(y) deve restituire true se e solo se y.equals(x) restituisce true.
  • Transitività: Per x, y, e z non nulli, se x.equals(y) e y.equals(z) sono true, allora x.equals(z) deve essere true.
  • Coerenza: Per x e y non nulli, molteplici chiamate a x.equals(y) devono restituire coerentemente true o false, fintanto che le informazioni usate per il confronto non cambiano.
  • Per ogni x non nullo, x.equals(null) deve restituire false.

Si consiglia di usare Objects.equals(obj1, obj2) per confrontare in modo sicuro gli oggetti, poiché gestisce correttamente null.

Sempre ridefinire hashCode() quando si ridefinisce equals(), in conformità con il contratto generale di Object.hashCode: se due oggetti sono uguali secondo equals(), i loro hashCode, restituiti da hashCode(), devono essere uguali. La condizione inversa non è richiesta. La mancata osservanza di questa regola può causare comportamenti errati delle collezioni basate su tabelle hash (ad esempio, HashMap, HashSet).

// Esempio di hashCode corrispondente per MyClass
class MyClass {
    private int id;
    private String name;

    // ... costruttore e equals come sopra ...

    @Override
    public int hashCode() {
        // Uso di Objects.hash per calcolare facilmente l'hash
        return Objects.hash(id, name);
    }
}

Può essere generato automaticamente con IDE (IntelliJ IDEA, Eclipse) i metodi equals e hashCode, che rappresenta una buona pratica.

Usa instanceof invece di getClass() solo se la classe fa parte di una gerarchia di ereditarietà e vuoi che oggetti di superclasse e sottoclasse siano considerati uguali se hanno lo stesso stato. Nella maggior parte dei casi, è preferibile usare getClass() per un controllo rigoroso.