Ответ
Все классы Java неявно наследуют от java.lang.Object. Три наиболее важных метода:
1. public boolean equals(Object obj)
- Назначение: Сравнение объектов на логическое равенство
- Контракт:
- Рефлексивность:
x.equals(x)→true - Симметричность:
x.equals(y)⇔y.equals(x) - Транзитивность:
x.equals(y) && y.equals(z)⇒x.equals(z) - Консистентность: многократные вызовы дают одинаковый результат
x.equals(null)→false
- Рефлексивность:
2. public int hashCode()
- Назначение: Возвращает целочисленный хеш-код для использования в хеш-коллекциях
- Критическое правило: Если
x.equals(y) == true, тоx.hashCode() == y.hashCode()
3. public String toString()
- Назначение: Строковое представление объекта для отладки и логирования
- По умолчанию:
getClass().getName() + "@" + Integer.toHexString(hashCode())
Пример корректной реализации:
public final class Person {
private final String name;
private final int age;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person person = (Person) o;
return age == person.age && name.equals(person.name);
}
@Override
public int hashCode() {
// Используем Objects.hash() для консистентности
return Objects.hash(name, age);
}
@Override
public String toString() {
return String.format("Person{name='%s', age=%d}", name, age);
}
}
Важные нюансы:
Для equals():
// Правильная сигнатура - принимает Object
@Override
public boolean equals(Object other) { /* ... */ }
// НЕПРАВИЛЬНО - это перегрузка, а не переопределение!
public boolean equals(Person other) { /* ... */ }
Для hashCode():
// Плохая практика - постоянный hashCode
@Override
public int hashCode() {
return 42; // Убивает производительность HashMap/HashSet
}
Для toString():
// Полезно для отладки
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("name", name)
.add("age", age)
.toString();
}
Связь с коллекциями:
HashMap,HashSetиспользуютhashCode()иequals()- Сортированные коллекции используют
compareTo()/Comparator, а неequals()
Рекомендация: Всегда переопределяйте эти три метода вместе для классов-значений (value objects).