Sobes.tech
Middle

Jak poprawnie nadpisać metodę equals w Java?

sobes.tech AI

Odpowiedź od AI

// Przykład minimalnej poprawnej nadpisania metody equals
class MyClass {
    private int id;
    private String name;

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

    @Override // Obowiązkowa adnotacja
    public boolean equals(Object o) {
        // 1. Sprawdzenie tożsamości
        if (this == o) return true;
        // 2. Sprawdzenie na null i zgodność klas
        // Używamy getClass() do ścisłej kontroli
        if (o == null || getClass() != o.getClass()) return false;
        // 3. Rzutowanie
        MyClass myClass = (MyClass) o;
        // 4. Porównanie istotnych pól
        return id == myClass.id &&
               // Używamy Objects.equals do porównania obiektów (obsługuje null)
               Objects.equals(name, myClass.name);
    }
}

Zasady poprawnego nadpisywania equals (zgodnie z kontraktem Object.equals):

  • Refleksyjność: Dla każdego nie null x, x.equals(x) powinno zwracać true.
  • Symetryczność: Dla dowolnych nie null x i y, x.equals(y) zwraca true wtedy i tylko wtedy, gdy y.equals(x) zwraca true.
  • Przechodniość: Dla nie null x, y, z, jeśli x.equals(y) i y.equals(z)true, to x.equals(z) też musi być true.
  • Spójność: Wielokrotne wywołanie x.equals(y) powinno zwracać ten sam wynik, o ile dane użyte do porównania się nie zmieniły.
  • Dla nie null x, x.equals(null) musi zwracać false.

Zaleca się używanie Objects.equals(obj1, obj2) do bezpiecznego porównywania obiektów, ponieważ obsługuje null poprawnie.

Zawsze nadpisuj hashCode(), gdy nadpisujesz equals(), zgodnie z ogólnym kontraktem Object.hashCode: jeśli dwa obiekty są równe według equals(), to ich hashCode() musi być taki sam. Odwrotna zależność nie jest wymagana. Nieprzestrzeganie tego może prowadzić do nieprawidłowego działania kolekcji opartych na tablicach haszujących (np. HashMap, HashSet).

// Przykład odpowiedniego hashCode dla MyClass
class MyClass {
    private int id;
    private String name;

    // ... konstruktor i equals jak wyżej ...

    @Override
    public int hashCode() {
        // Użycie Objects.hash do wygodnego obliczania hasha
        return Objects.hash(id, name);
    }
}

Metody equals i hashCode można generować automatycznie w IDE (IntelliJ IDEA, Eclipse), co jest dobrą praktyką.

Używaj instanceof zamiast getClass() tylko wtedy, gdy klasa jest częścią hierarchii dziedziczenia i chcesz, aby obiekty nadklasy i podklasy były uważane za równe, jeśli mają ten sam stan. W większości przypadków lepiej jest używać getClass() dla ścisłej kontroli.