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
xiy,x.equals(y)zwracatruewtedy i tylko wtedy, gdyy.equals(x)zwracatrue. - Przechodniość: Dla nie null
x,y,z, jeślix.equals(y)iy.equals(z)sątrue, tox.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.