Object ·
‹ Предыдущий Следующий ›
⏱ 5 минут чтения Обновлено: 2026-09-27

Класс Object в Java и его основные методы

Класс Object (java.lang.Object) — корень иерархии классов в Java: каждый класс неявно наследуется от Object, даже если в объявлении нет extends Object. Object — единственный класс без суперкласса. Поэтому методы класса Object — equals(), hashCode(), toString(), getClass(), clone(), wait(), notify() и другие — доступны у любого объекта, включая массивы. Примитивные типы (int, double и т.д.) объектами не являются и этих методов не имеют.

Все методы класса Object: таблица

В классе Object объявлено 11 публичных и защищённых методов. Часть из них можно переопределять, а методы с модификатором final — нельзя.

Метод Модификаторы Назначение Можно переопределить?
boolean equals(Object obj) public Проверяет, равен ли другой объект текущему Да, часто
int hashCode() public Возвращает хэш-код объекта для HashMap, HashSet и других хэш-коллекций Да, всегда вместе с equals()
String toString() public Возвращает строковое представление объекта Да, часто
Class<?> getClass() public final Возвращает класс объекта во время выполнения (runtime-тип) Нет
Object clone() protected Создаёт копию объекта; класс должен реализовать Cloneable, иначе CloneNotSupportedException Да, редко
void finalize() protected, deprecated Вызывался сборщиком мусора перед удалением объекта; устарел Не рекомендуется
void notify() public final Пробуждает один поток, ожидающий на мониторе этого объекта Нет
void notifyAll() public final Пробуждает все потоки, ожидающие на мониторе этого объекта Нет
void wait() public final Переводит поток в ожидание, пока другой поток не вызовет notify()/notifyAll() Нет
void wait(long timeout) public final То же, но ожидание не дольше timeout миллисекунд Нет
void wait(long timeout, int nanos) public final То же, с дополнительной точностью в наносекундах Нет

finalize() устарел

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

Какие методы Object переопределяют на практике

В повседневной разработке переопределяют в основном три метода класса Object:

  • equals() — чтобы сравнивать объекты по содержимому (полям), а не по ссылке;
  • hashCode() — обязательно вместе с equals(), иначе объекты некорректно работают в HashMap и HashSet;
  • toString() — чтобы получать читаемый вывод в логах, отладчике и при печати.

Методы getClass(), wait(), notify() и notifyAll() объявлены как final, поэтому переопределить их невозможно. clone() переопределяют редко — вместо него чаще пишут конструктор копирования или фабричный метод.

Подробнее: правила сравнения объектов и контракт equals()/hashCode() разобраны в уроке Метод equals() в Java, а форматирование строкового представления — в уроке Метод toString() в Java. Метод clone() рассмотрен в уроке Клонирование объектов в Java.

Как работают equals, hashCode и toString по умолчанию

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

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

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public static void main(String[] args) {
        Point a = new Point(1, 2);
        Point b = new Point(1, 2);

        System.out.println(a.equals(b));   // false - сравниваются ссылки
        System.out.println(a);             // Point@1b6d3586 (хэш будет другим)
        System.out.println(a.getClass());  // class Point
    }
}

Переопределим методы, чтобы точки с одинаковыми координатами считались равными:

import java.util.Objects;

public class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Point other = (Point) o;
        return x == other.x && y == other.y;
    }

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

    @Override
    public String toString() {
        return "Point{x=" + x + ", y=" + y + "}";
    }
}

Теперь new Point(1, 2).equals(new Point(1, 2)) вернёт true, HashSet найдёт такую точку, а System.out.println выведет Point{x=1, y=2}.

Современная альтернатива

Начиная с Java 16 для простых классов-носителей данных можно объявить record Point(int x, int y) {} — компилятор сам сгенерирует корректные equals(), hashCode() и toString() по всем компонентам.

Методы wait, notify и notifyAll

Методы wait(), notify() и notifyAll() служат для взаимодействия потоков. Они объявлены в Object, потому что монитором (объектом блокировки) в Java может быть любой объект. Вызывать их можно только внутри блока или метода synchronized по этому же объекту — иначе будет выброшено IllegalMonitorStateException.

synchronized (lock) {
    while (!ready) {
        lock.wait();      // освобождает монитор и ждёт
    }
}

// в другом потоке
synchronized (lock) {
    ready = true;
    lock.notifyAll();     // будит все ожидающие потоки
}

Подробно механизм разобран в уроке Межпотоковые коммуникации.

Частые ошибки при работе с методами Object

  • Переопределить equals() без hashCode(). Равные объекты попадут в разные корзины хэш-таблицы, и HashSet.contains() или HashMap.get() их не найдут.
  • Перегрузить вместо переопределения. Метод equals(Point p) — это перегрузка, а не переопределение: коллекции вызывают equals(Object). Аннотация @Override ловит эту ошибку на этапе компиляции.
  • Вызывать wait() вне synchronized. Результат — IllegalMonitorStateException во время выполнения.
  • Полагаться на finalize() для закрытия ресурсов. Вызов не гарантирован; используйте try-with-resources.
  • Вызывать clone() у класса без Cloneable. Реализация Object выбросит CloneNotSupportedException.

Презентация с видео на Patreon →

Часто задаваемые вопросы

Сколько методов в классе Object в Java?

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

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

По контракту равные по equals() объекты обязаны иметь одинаковый hashCode(). Хэш-коллекции сначала ищут корзину по хэш-коду и только потом сравнивают через equals(), поэтому без согласованного hashCode() HashMap и HashSet не найдут равный объект.

Наследуют ли интерфейсы класс Object?

Нет, интерфейс не наследуется от класса. Но по спецификации языка интерфейс без суперинтерфейсов неявно объявляет абстрактные версии public-методов Object, поэтому через переменную интерфейсного типа можно вызвать equals(), hashCode() или toString(). Реализовать их как default-методы в интерфейсе нельзя.

Почему wait() и notify() находятся в Object, а не в Thread?

Потому что в Java монитором может быть любой объект, а ожидание и уведомление привязаны к монитору, а не к потоку. Поток ждёт на конкретном объекте-блокировке, и другой поток будит его через тот же объект.

Видео объяснение

Предпочитаете видеоформат? Посмотрите этот урок с примерами и объяснениями.

Комментарии

Зарегистрируйтесь или войдите, чтобы иметь возможность оставить комментарий.