Класс Object
Роль
java.lang.Object — корень иерархии ссылочных типов Java. Если класс не указывает extends, он неявно наследует Object. Массивы тоже являются объектами; примитивы — нет.
Object text = "ready";
Object numbers = new int[] {1, 2, 3};Переменная типа Object может ссылаться почти на любой объект, но через неё доступны только методы статического типа Object. Реальная переопределённая реализация выбирается полиморфно во время выполнения.
Методы
| Метод | Назначение и контракт |
|---|---|
getClass() | возвращает реальный runtime-класс объекта |
equals(Object) | определяет логическое равенство |
hashCode() | согласован с equals; нужен хеш-структурам |
toString() | текстовое представление для диагностики |
clone() | защищённый механизм поверхностного копирования; требует Cloneable, обычно неудобен |
wait() | освобождает монитор и ждёт сигнал/таймаут |
notify() | будит один ожидающий на том же мониторе поток |
notifyAll() | будит все ожидающие на том же мониторе потоки |
finalize() | устаревший и ненадёжный механизм финализации; не использовать для освобождения ресурсов |
wait, notify и notifyAll нужно вызывать, владея монитором объекта, то есть внутри соответствующего synchronized. Ожидание всегда помещают в цикл: возможны ложные пробуждения, а условие мог изменить другой поток.
synchronized (monitor) {
while (!ready) {
monitor.wait();
}
}Для нового конкурентного кода чаще подходят блокировки и синхронизаторы из java.util.concurrent.
equals и hashCode
Реализация Object.equals сравнивает идентичность (this == other). Классы-значения обычно переопределяют метод:
record UserId(long value) {}
new UserId(7).equals(new UserId(7)); // trueГлавный инвариант: если a.equals(b) равно true, то a.hashCode() == b.hashCode(). Обратное не обязательно — коллизии допустимы. Подробно: Equals и hashCode.
toString
Реализация по умолчанию строит строку из имени класса и хеша; это не адрес объекта. Для доменных типов полезен информативный toString, но в него нельзя бездумно включать пароли, токены и персональные данные.
Копирование и ресурсы
clone выполняет поверхностное копирование: ссылки внутри копии всё ещё указывают на те же вложенные объекты. Обычно яснее написать копирующий конструктор или фабрику.
finalize не гарантирует своевременный вызов. Файлы и соединения закрывают через AutoCloseable и try-with-resources, а не через сборщик мусора.
Ловушки
- Переопределить
equals, но оставить несовместимыйhashCode. - Считать
toStringбезопасным местом для любых данных. - Вызывать
waitвнеsynchronizedили проверять условие черезif. - Считать
cloneглубоким копированием. - Пытаться вручную вызвать или полагаться на
finalize.
Вопросы на собеседовании
- Какие типы не наследуют
Object? - Как связан контракт
equalsсhashCode? - Почему
waitвызывают в цикле и под монитором? - Чем поверхностная копия отличается от глубокой?
- Почему
finalizeнельзя использовать для управления ресурсами?
Связанные заметки
Основы ООП · Объекты Java · Equals и hashCode · Переопределение Java · Garbage collector · Работа с исключениями в Java