Какие три основных метода наследуются всеми объектами Java от класса Object?

«Какие три основных метода наследуются всеми объектами Java от класса Object?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Все классы Java неявно наследуют от java.lang.Object. Три наиболее важных метода:

1. public boolean equals(Object obj)

  • Назначение: Сравнение объектов на логическое равенство
  • Контракт:
    1. Рефлексивность: x.equals(x)true
    2. Симметричность: x.equals(y)y.equals(x)
    3. Транзитивность: x.equals(y) && y.equals(z)x.equals(z)
    4. Консистентность: многократные вызовы дают одинаковый результат
    5. 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).