equals() i hashCode()
Część sekcji Programowanie obiektowe ścieżki Java w Coddy. Lekcja 42 z 87.
Podczas porównywania obiektów w Javie operator == sprawdza, czy dwa odwołania wskazują tę samą lokalizację w pamięci. Aby porównać rzeczywistą zawartość obiektów, musisz nadpisać metodę equals().
public class Person {
private String name;
private int age;
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age && name.equals(person.name);
}
}Metoda equals() ma standardowy schemat: najpierw sprawdź, czy to ten sam obiekt, następnie zweryfikuj typ, a na koniec porównaj odpowiednie pola.
Za każdym razem, gdy nadpisujesz equals(), musisz również nadpisać hashCode(). To umowa w Javie: obiekty, które są równe, muszą mieć ten sam kod skrótu. Kolekcje oparte na kodach skrótu, takie jak HashMap i HashSet, polegają na tej zasadzie, aby działać poprawnie.
@Override
public int hashCode() {
return Objects.hash(name, age);
}Metoda narzędziowa Objects.hash() generuje kod skrótu na podstawie tych samych pól co equals(). Jeśli dwa obiekty Person mają takie samo imię i wiek, zostaną uznane za równe i wygenerują identyczne kody skrótu, co zapewni spójne działanie w kolekcjach.
Wyzwanie
ŁatwyZbudujmy system ewidencji studentów, który prawidłowo implementuje równość obiektów. Utworzysz klasę Student, w której dwóch studentów jest uznawanych za równych, jeśli mają ten sam numer identyfikacyjny i imię, niezależnie od tego, czy są tym samym obiektem w pamięci.
Rozmieścisz swój kod w dwóch plikach:
Student.java: Utwórz klasę reprezentującą studenta z trzema prywatnymi polami:studentId(String),name(String) igpa(double). Dodaj konstruktor inicjalizujący wszystkie pola oraz metody pobierające dla każdego pola.Nadpisz metodę
equals(), aby dwa obiekty Student były uznawane za równe, gdy mają tę samą wartośćstudentIdORAZ tę samą wartośćname. Zastosuj standardowy schemat: sprawdź, czy to ta sama referencja, sprawdź wartość null i typ, a następnie porównaj odpowiednie pola.Nadpisz metodę
hashCode(), używającObjects.hash()z tymi samymi polami, które są używane wequals(). Pamiętaj, aby zaimportowaćjava.util.Objectsna początku pliku.Main.java: Ożyw swoją klasę Student, porównując obiekty studentów. Otrzymasz sześć danych wejściowych reprezentujących dwóch studentów: najpierw numer identyfikacyjny, imię i GPA pierwszego studenta, a następnie numer identyfikacyjny, imię i GPA drugiego studenta.Utwórz oba obiekty Student, a następnie wykonaj trzy porównania i wypisz wyniki:
- Wypisz
Same reference:, a następnie informację, czy pierwszy student jest równy samemu sobie (powinno to zawsze być true) - Wypisz
Content equality:, a następnie informację, czy pierwszy student jest równy drugiemu studentowi (zgodnie z implementacją equals) - Wypisz
Hash codes match:, a następnie informację, czy obaj studenci mają ten sam kod skrótu
- Wypisz
Otrzymasz sześć danych wejściowych: numer identyfikacyjny pierwszego studenta (String), imię pierwszego studenta (String), GPA pierwszego studenta (double), numer identyfikacyjny drugiego studenta (String), imię drugiego studenta (String) oraz GPA drugiego studenta (double).
Zwróć uwagę, że gdy dwóch studentów ma takie same numery identyfikacyjne i imiona, zarówno equals() zwraca true, JAK I ich kody skrótu są zgodne. Tę regułę musisz zachować!
Spróbuj swoich sił
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Wczytaj dane pierwszego studenta
String id1 = scanner.nextLine();
String name1 = scanner.nextLine();
double gpa1 = scanner.nextDouble();
scanner.nextLine(); // pobierz znak nowej linii
// Wczytaj dane drugiego studenta
String id2 = scanner.nextLine();
String name2 = scanner.nextLine();
double gpa2 = scanner.nextDouble();
// TODO: Utwórz dwa obiekty Student na podstawie danych wejściowych
// TODO: Wypisz "Same reference: ", a następnie informację, czy student1 jest równy samemu sobie
// TODO: Wypisz "Content equality: ", a następnie informację, czy student1 jest równy student2
// TODO: Wypisz "Hash codes match: ", a następnie informację, czy obaj studenci mają ten sam kod hash
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe thisMetodyPola (atrybuty)Metoda konstruktoraPrzeciążanie konstruktoraPodsumowanie — prosty kalkulator4Dziedziczenie
Podstawy dziedziczenia (extends)Słowo kluczowe superPrzesłanianie metod (@Override)Łańcuch wywołań konstruktorówKlasa ObjectDziedziczenie jedno- i wielopoziomoweDlaczego Java nie obsługuje wielodziedziczenia klasPodsumowanie – hierarchia pracowników7Metody specjalne i klasa Object
Metoda toString()equals() i hashCode()Metoda clone()compareTo() i ComparableInterfejs ComparatorPodsumowanie — własne sortowanie10Obsługa wyjątków w programowaniu obiektowym
Hierarchia klas wyjątkówWłasne wyjątkiBłędy sprawdzane a niesprawdzaneWzorzec try-with-resourcesPodsumowanie – zweryfikowany użytkownik2Modyfikatory dostępu i enkapsulacja
Przegląd poziomów dostępuMetody pobierające i ustawiająceUkrywanie informacjiSłowo kluczowe finalPodsumowanie — menedżer kont bankowych5Polimorfizm
Podstawy przeciążania metodPrzesłanianie metod (w czasie wykonywania)Rzutowanie w górę i w dółOperator instanceofKlasy i metody abstrakcyjnePowtórka — kalkulator figur8Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieAgregacja a kompozycjaKlasy wewnętrzne, zagnieżdżone i anonimoweEnumy i metody enumówRekordy (Java 16+)Klasy zapieczętowane (Java 17+)11Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec BuilderWzorzec ObserverWzorzec Strategy3Właściwości klas i składowe statyczne
Zmienne instancji a zmienne statyczneMetody statyczneBloki statyczneStałe (static final)Powtórka – Counter i Utility6Interfejsy i klasy abstrakcyjne
Wprowadzenie do interfejsówImplementowanie interfejsówImplementacja wielu interfejsówMetody domyślne i statyczne w interfejsieKlasy abstrakcyjne a interfejsyInterfejsy funkcyjnePodsumowanie — system płatnościPoćwicz samodzielnie: Kompilator Java online