Object - Вопросы

Всего: 6 вопросов

1. 

Что такое класс Object в Java?

Класс Object (java.lang.Object) — корень иерархии классов в Java. Каждый класс неявно наследуется от Object, даже если в объявлении нет extends Object, а сам Object — единственный класс без суперкласса.

Поэтому методы класса Object (equals(), hashCode(), toString(), getClass(), clone(), wait(), notify() и другие) доступны у любого объекта, включая массивы, а переменная типа Object может ссылаться на любой объект. Примитивы (int, double) объектами не являются и этих методов не имеют. Интерфейсы от Object не наследуются, но неявно объявляют его public-методы.

2. 

Какие методы есть у класса Object в Java и какие из них нельзя переопределить?

В классе Object 11 публичных и защищённых методов: equals(), hashCode(), toString(), getClass(), clone(), finalize(), notify(), notifyAll() и три перегрузки wait() — wait(), wait(long), wait(long, int).

Шесть методов объявлены final и не переопределяются: getClass(), notify(), notifyAll() и все три wait(). На практике переопределяют equals(), hashCode() (всегда вместе с equals) и toString(); clone() — редко, finalize() устарел и переопределять его не рекомендуется.

3. 

Как работают методы equals(), hashCode() и toString() класса Object по умолчанию?

Если метод не переопределён, используется реализация из Object:

  • equals() сравнивает ссылки, то есть работает как ==: два разных объекта с одинаковыми полями не равны;
  • hashCode() возвращает идентификационный хэш-код конкретного экземпляра, поэтому у разных объектов он почти всегда разный;
  • toString() возвращает getClass().getName() + "@" + Integer.toHexString(hashCode()), например Point@1b6d3586.

Чтобы сравнивать объекты по полям и получать читаемый вывод, эти методы переопределяют или объявляют record (Java 16+), для которого компилятор генерирует их сам.

4. 

Почему при переопределении equals() в Java нужно переопределять и hashCode()?

По контракту класса Object равные по equals() объекты обязаны иметь одинаковый hashCode(). Обратное не требуется: у неравных объектов хэш-коды могут совпасть (коллизия).

HashMap и HashSet сначала выбирают корзину по хэш-коду и только потом сравнивают элементы через equals(). Если переопределить только equals(), равные объекты попадут в разные корзины, и set.contains(new Point(1, 2)) вернёт false. Правильно — строить оба метода по одним и тем же полям:

@Override
public int hashCode() {
    return Objects.hash(x, y);
}
5. 

Зачем нужны методы clone() и finalize() класса Object и почему их используют редко?

clone() (protected) создаёт поверхностную копию объекта. Класс должен реализовать маркерный интерфейс Cloneable, иначе реализация Object выбросит CloneNotSupportedException. Вместо clone() обычно пишут конструктор копирования или фабричный метод.

finalize() вызывался сборщиком мусора перед удалением объекта, но вызов не гарантирован. Метод помечен @Deprecated с Java 9 и как подлежащий удалению — с Java 18 (JEP 421). Для освобождения ресурсов используйте try-with-resources с AutoCloseable, а в крайних случаях — java.lang.ref.Cleaner.

6. 

Почему wait(), notify() и notifyAll() объявлены в классе Object и где их можно вызывать?

В Java монитором (объектом блокировки) может быть любой объект, а ожидание и уведомление привязаны к монитору, а не к потоку — поэтому методы находятся в Object, а не в Thread. Все они объявлены final.

Вызывать их можно только внутри блока или метода synchronized по тому же объекту, иначе будет выброшено IllegalMonitorStateException. wait() вызывают в цикле while, который перепроверяет условие:

synchronized (lock) {
    while (!ready) {
        lock.wait();
    }
}
Страница 1 из 1