Sobes.tech
Middle

Πώς υπερισχύει σωστά η μέθοδος equals στη Java;

sobes.tech AI

Απάντηση από AI

// Παράδειγμα ελάχιστης σωστής επαναπροσδιορισμού του equals
class MyClass {
    private int id;
    private String name;

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

    @Override // Υποχρεωτική σημείωση
    public boolean equals(Object o) {
        // 1. Έλεγχος ταυτότητας
        if (this == o) return true;
        // 2. Έλεγχος null και αντιστοιχία κλάσεων
        // Χρησιμοποιούμε getClass() για αυστηρό έλεγχο
        if (o == null || getClass() != o.getClass()) return false;
        // 3. Μετατροπή τύπου
        MyClass myClass = (MyClass) o;
        // 4. Σύγκριση σημαντικών πεδίων
        return id == myClass.id &&
               // Χρησιμοποιούμε Objects.equals για σύγκριση αντικειμένων (λαμβάνει υπόψη null)
               Objects.equals(name, myClass.name);
    }
}

Κανόνες για σωστό επαναπροσδιορισμό του equals (σύμφωνα με τη σύμβαση του Object.equals):

  • Αντανάκλαση: Για κάθε μη null x, το x.equals(x) πρέπει να επιστρέφει true.
  • Συμμετρία: Για κάθε μη null x και y, το x.equals(y) πρέπει να επιστρέφει true αν και μόνο αν το y.equals(x) επιστρέφει true.
  • Μεταβατικότητα: Για κάθε μη null x, y, και z, αν το x.equals(y) και το y.equals(z) είναι true, τότε το x.equals(z) πρέπει να είναι true.
  • Συνεπτικότητα: Για κάθε μη null x και y, πολλαπλές κλήσεις του x.equals(y) πρέπει να επιστρέφουν το ίδιο αποτέλεσμα, όσο δεν αλλάζουν οι πληροφορίες που χρησιμοποιούνται για τη σύγκριση.
  • Για κάθε μη null x, το x.equals(null) πρέπει να επιστρέφει false.

Συνιστάται η χρήση Objects.equals(obj1, obj2) για ασφαλή σύγκριση αντικειμένων, καθώς χειρίζεται σωστά το null.

Πάντα να επαναπροσδιορίζετε το hashCode() όταν επαναπροσδιορίζετε το equals(), σύμφωνα με τη γενική σύμβαση του Object.hashCode: αν δύο αντικείμενα είναι ίσα σύμφωνα με το equals(), τα hash codes τους, που επιστρέφονται από το hashCode(), πρέπει να είναι ίδια. Η αντίστροφη δεν απαιτείται. Η μη τήρηση αυτής της αρχής μπορεί να οδηγήσει σε λανθασμένη λειτουργία συλλογών που βασίζονται σε πίνακες κατακερματισμού (π.χ. HashMap, HashSet).

// Παράδειγμα κατάλληλου hashCode για MyClass
class MyClass {
    private int id;
    private String name;

    // ... κατασκευαστής και equals όπως παραπάνω ...

    @Override
    public int hashCode() {
        // Χρήση Objects.hash για εύκολη υπολογισμό του hash
        return Objects.hash(id, name);
    }
}

Μπορείτε να δημιουργήσετε αυτόματα τις μεθόδους equals και hashCode χρησιμοποιώντας IDEs (IntelliJ IDEA, Eclipse), κάτι που αποτελεί καλή πρακτική.

Χρησιμοποιήστε instanceof αντί για getClass() μόνο αν η κλάση αποτελεί μέρος ιεραρχίας κληρονομικότητας και θέλετε τα αντικείμενα της υπερκλάσης και της υποκλάσης να θεωρούνται ίσα αν έχουν την ίδια κατάσταση. Στις περισσότερες περιπτώσεις, προτιμάται η χρήση getClass() για αυστηρό έλεγχο.