Методы класса Object в Java

Класс Object является корнем иерархии классов. У каждого класса есть Object как суперкласс. Все объекты, включая массивы, реализуют методы этого класса.

Методы класса Object

Метод getClass()

public final Class getClass()

Возвращает класс времени исполнения (runtime class) этого Object. Возвращенный объект Class - это объект, который заблокирован статическими синхронизированными методами представленного класса.

Фактический тип результата - Class<? extends |X|> где |X| заменяется статическим типом выражения, для которого вызывается getClass. Например, в этом фрагменте кода не требуется приведение:

Number n = 0; 
Class c = n.getClass();

Метод getClass() возвращает:

Объект Class, представляющий класс времени исполнения (runtime class) этого объекта.

Метод hashCode

public int hashCode()

Возвращает значение хэш-кода для объекта. Этот метод поддерживается для использования хэш-таблиц, таких как те, что предоставляются HashMap.

Основной контракт метода hashCode:

  • Всякий раз, когда он вызывается для одного и того же объекта более одного раза во время выполнения приложения Java, метод hashCode должен последовательно возвращать одно и то же целое число при условии, что никакая информация, используемая в сравнениях equals для объекта, не изменяется. Это целое число не должно оставаться согласованным между одним исполнением приложения и другим исполнением того же приложения.
  • Если два объекта равны в соответствии с методом equals(Object), то вызов метода hashCode для каждого из двух объектов должен привести к одному и тому же целочисленному результату.
  • Не требуется, чтобы, если два объекта были неравны в соответствии с методом equals(java.lang.Object), то вызов метода hashCode для каждого из двух объектов должен давать разные целочисленные результаты. Тем не менее, программист должен знать, что выдача различных целочисленных результатов для неравных объектов может повысить производительность хэш-таблиц.

Насколько это практически целесообразно, метод hashCode, определенный классом Object, возвращает разные целые числа для разных объектов. (Обычно это реализуется путем преобразования внутреннего адреса объекта в целое число, но этот метод реализации не требуется языком программирования Java.)

Метод hashCode возвращает:

Целочисленное (int) значение хэш-кода для этого объекта.

Метод equals

public boolean equals(Object obj)

Указывает, равен ли какой-либо другой объект этому объекту.

Метод equals реализует отношение эквивалентности для ненулевых ссылок на объекты:

  • Оно рефлексивно: для любого ненулевого ссылочного значения x, x.equals(x) должно возвращать true.
  • Оно симметрично: для любых ненулевых ссылочных значений x и y x.equals(y) должен возвращать true, только если y.equals(x) возвращает true.
  • Оно транзитивно: для любых ненулевых ссылочных значений x, y и z, если x.equals(y) возвращает true, а y.equals(z) возвращает true, тогда x.equals(z) должен возвращать true.
  • Оно непротиворечиво (консистентно): для любых ненулевых ссылочных значений x и y множественные вызовы x.equals(y) последовательно возвращают true или последовательно возвращают false при условии, что никакая информация, используемая в сравнениях equals на объектах, не изменяется.
  • Для любого ненулевого ссылочного значения x, x.equals(null) должен возвращать false.

Метод equals для класса Object реализует максимально различающее возможное отношение эквивалентности на объектах; то есть для любых ненулевых ссылочных значений x и y этот метод возвращает true только тогда, когда x и y ссылаются на один и тот же объект (x == y имеет значение true).

Обратите внимание, что обычно необходимо переопределять метод hashCode всякий раз, когда метод equals переопределяется, чтобы поддерживать общий контракт для метода hashCode, в котором говорится, что равные объекты должны иметь одинаковые хэш-коды.

Параметры:

obj - эталонный объект для сравнения.

Метод equals возвращает:

Значение true, если этот объект совпадает с аргументом obj; false в противном случае.

Метод clone

protected Object clone() throws CloneNotSupportedException

Создает и возвращает копию этого объекта. Точное значение "копия" может зависеть от класса объекта. Общее намерение состоит в том, что для любого объекта x, выражение:

x.clone() != x

будет верно, и это выражение:

x.clone().getClass() == x.getClass()

будет верно, но это не абсолютные требования. Хотя обычно это так:

x.clone().equals(x)

будет верно, это не является абсолютным требованием.

По соглашению, возвращаемый объект должен быть получен путем вызова super.clone. Если класс и все его суперклассы (кроме Object) подчиняются этому соглашению, это будет иметь место в том случае, если x.clone().getClass() == x.getClass().

По соглашению объект, возвращаемый этим методом, должен быть независимым от этого объекта (который клонируется). Для достижения этой независимости может потребоваться изменить одно или несколько полей объекта, возвращаемого super.clone, перед его возвратом. Как правило, это означает копирование любых изменяемых объектов, которые составляют внутреннюю "глубокую структуру" клонируемого объекта, и замену ссылок на эти объекты ссылками на копии. Если класс содержит только примитивные поля или ссылки на неизменяемые объекты, то обычно бывает так, что нет необходимости изменять поля в объекте, возвращаемом super.clone.

Метод clone для класса Object выполняет определенную операцию клонирования. Во-первых, если класс этого объекта не реализует интерфейс Cloneable, генерируется исключение CloneNotSupportedException. Обратите внимание, что считается, что все массивы реализуют интерфейс Cloneable и что тип возвращаемого значения метода clone типа массива T[] равен T[], где T - любой ссылочный или примитивный тип. В противном случае этот метод создает новый экземпляр класса этого объекта и инициализирует все его поля точно содержимым соответствующих полей этого объекта, как если бы он был назначен; содержимое полей не клонируется. Таким образом, этот метод выполняет "поверхностную копию" ("shallow copy") этого объекта, а не "глубокую копию" ("deep copy").

Класс Object сам по себе не реализует интерфейс Cloneable, поэтому вызов метода clone для объекта, класс которого Object, приведет к возникновению исключения во время выполнения.

Метод clone возвращает:

клон этого экземпляра.

Метод clone выбрасывает:

CloneNotSupportedException - если класс объекта не поддерживает интерфейс Cloneable. Подклассы, которые переопределяют метод clone, могут также выдать это исключение, чтобы указать, что экземпляр не может быть клонирован.

Метод toString

public String toString()

Возвращает строковое представление объекта. В общем случае метод toString возвращает строку, которая является "текстовым представлением" этого объекта. Результатом должно быть краткое, но информативное представление, которое легко читается человеком. Рекомендуется, чтобы все подклассы переопределяли этот метод.

Метод toString для класса Object возвращает строку, состоящую из имени класса, экземпляром которого является объект, символа знака "@" и шестнадцатеричного представления без знака хэш-кода объекта. Другими словами, этот метод возвращает строку, равную значению:

getClass().getName() + '@' + Integer.toHexString(hashCode())

Метод toString возвращает:

строковое представление объекта.

Метод notify

public final void notify()

Пробуждает один поток, который ожидает на мониторе этого объекта. Если какие-либо потоки ожидают этого объекта, один из них выбирается для пробуждения. Выбор является произвольным и происходит на усмотрение реализации. Поток ожидает на мониторе объекта, вызывая один из методов wait.

Пробужденный поток не сможет продолжить работу, пока текущий поток не снимет блокировку этого объекта. Пробужденный поток будет конкурировать обычным образом с любыми другими потоками, которые могут активно конкурировать за синхронизацию на этом объекте; например, пробужденный поток не имеет надежных привилегий или недостатков в качестве следующего потока для блокировки этого объекта.

Этот метод должен вызываться только потоком, который является владельцем монитора этого объекта. Поток становится владельцем монитора объекта одним из трех способов:

  • Выполняя synchronized метод экземпляра этого объекта.
  • Выполняя тело synchronized выражения, которое синхронизируется на объекте.
  • Для объектов типа Class, выполняя synchronized static метод этого класса.

Только один поток одновременно может владеть монитором объекта.

Выбрасывает исключения:

IllegalMonitorStateException - если текущий поток не является владельцем монитора этого объекта.

Метод notifyAll

public final void notifyAll()

Пробуждает все потоки, которые ожидают на мониторе этого объекта. Поток ожидает на мониторе объекта, вызывая один из методов wait.

Пробужденные потоки не смогут продолжить работу, пока текущий поток не снимет блокировку этого объекта. Пробужденные потоки будут конкурировать обычным образом с любыми другими потоками, которые могут активно конкурировать за синхронизацию на этом объекте; например, пробужденные потоки не имеют надежных привилегий или недостатков в качестве следующего потока для блокировки этого объекта.

Этот метод должен вызываться только потоком, который является владельцем монитора этого объекта.

Выбрасывает исключения:

IllegalMonitorStateException - если текущий поток не является владельцем монитора этого объекта.

Метод wait с аргументом timeout

public final void wait(long timeout) throws InterruptedException

Заставляет текущий поток ждать, пока другой поток не вызовет метод notify() или метод notifyAll() для этого объекта, или пока не истечет указанное количество времени.

Текущий поток должен владеть монитором этого объекта.

Этот метод заставляет текущий поток (назовем его T) поместить себя в набор ожидания для этого объекта, а затем отказаться от любых заявлений на синхронизацию этого объекта. Поток T становится отключенным для целей планирования потоков и остается бездействующим, пока не произойдет одно из четырех:

  • Какой-то другой поток вызывает метод notify для этого объекта, и поток T случайно выбирается в качестве потока, который нужно пробудить.
  • Другой поток вызывает метод notifyAll для этого объекта.
  • Какой-то другой поток прерывает поток Т.
  • Указанное количество реального времени истекло, более или менее. Однако, если timeout равен нулю, то реальное время не учитывается, и поток просто ждет, пока не получит уведомление.

Затем поток T удаляется из набора ожидания для этого объекта и снова включается для планирования потока. Затем он конкурирует обычным образом с другими потоками за право синхронизации на объекте; как только он получил контроль над объектом, все его заявки на синхронизацию с объектом восстанавливаются до состояния quo ante, то есть ситуации на момент вызова метода wait. Затем поток T возвращается из вызова метода ожидания. Таким образом, при возврате из метода ожидания состояние синхронизации объекта и потока Т точно такое же, как и при вызове метода ожидания.

Поток также может просыпаться без уведомления, прерывания или истечения тайм-аута, так называемое ложное пробуждение (spurious wakeup). Хотя это редко случается на практике, приложения должны защищаться от него, проверяя условие, которое должно было вызвать пробуждение потока, и продолжая ждать, если условие не выполняется. Другими словами, ожидания всегда должны происходить в циклах, например:

synchronized (obj) {
   while (<условие не выполняется>)
       obj.wait(timeout);
   ... // Выполняем действие подходящее для условия
}

Если текущий поток прерывается каким-либо потоком до или во время ожидания, генерируется исключение InterruptedException. Это исключение не выдается, пока состояние блокировки этого объекта не будет восстановлено, как описано выше.

Обратите внимание, что метод wait, поскольку он помещает текущий поток в набор ожидания для этого объекта, разблокирует только этот объект; любые другие объекты, по которым текущий поток может быть синхронизирован, остаются заблокированными, пока поток ожидает.

Этот метод должен вызываться только потоком, который является владельцем монитора этого объекта.

Параметры: timeout - максимальное время ожидания в миллисекундах.

Выбрасываемые исключения:

IllegalArgumentException - если значение timeout является отрицательным.

IllegalMonitorStateException - если текущий поток не является владельцем монитора объекта.

InterruptedException - если какой-либо поток прерывал текущий поток до или в то время, когда текущий поток ожидал уведомления. Прерванное состояние текущего потока очищается при возникновении этого исключения.

Метод wait с аргументами timeout и nanos

public final void wait(long timeout, int nanos) throws InterruptedException

Заставляет текущий поток ждать, пока другой поток не вызовет метод notify() или метод notifyAll() для этого объекта, или какой-либо другой поток прервет текущий поток, или пока не истекло определенное количество реального времени.

Этот метод аналогичен методу wait с одним аргументом, но он позволяет лучше контролировать время ожидания уведомления перед тем, как отказаться. Количество реального времени, измеряемое в наносекундах, определяется как:

1000000*timeout+nanos

Во всех других отношениях этот метод делает то же самое, что и метод wait(long) с одним аргументом. В частности, wait(0, 0) означает то же самое, что и wait(0).

Текущий поток должен владеть монитором этого объекта. Поток освобождает владельца этого монитора и ожидает, пока не произойдет одно из следующих двух условий:

  • Другой поток уведомляет потоки, ожидающие на мониторе этого объекта, чтобы он проснулся либо посредством вызова метода notify, либо метода notifyAll.
  • Истек срок ожидания, указанный аргументами: timeout миллисекунд плюс nanos наносекунд.

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

Как и в версии с одним аргументом, возможны прерывания и ложные пробуждения, и этот метод всегда должен использоваться в цикле:

synchronized (obj) {
   while (<условие не выполняется>)
       obj.wait(timeout, nanos);
   ... // Выполняем действие подходящее для условия
}

Этот метод должен вызываться только потоком, который является владельцем монитора этого объекта.

Параметры:
timeout - максимальное время ожидания в миллисекундах.
nanos - дополнительное время в диапазоне наносекунд 0-999999.

Выбрасываемые исключения:

IllegalArgumentException - если значение timeout является отрицательным или значение nanos не находится в диапазоне 0-999999.

IllegalMonitorStateException - если текущий поток не является владельцем монитора этого объекта.

InterruptedException - если какой-либо поток прерывал текущий поток до или в то время, когда текущий поток ожидал уведомления. Прерванное состояние текущего потока очищается при возникновении этого исключения.

Метод wait без аргументов

public final void wait() throws InterruptedException

Заставляет текущий поток ждать, пока другой поток не вызовет метод notify() или метод notifyAll() для этого объекта. Другими словами, этот метод ведет себя точно так же, как если бы он просто выполнял вызов wait(0).

Текущий поток должен владеть монитором этого объекта. Поток освобождает владельца этого монитора и ожидает, пока другой поток не уведомит потоки, ожидающие на мониторе этого объекта, чтобы он проснулся либо посредством вызова метода notify, либо метода notifyAll. Затем поток ожидает, пока не получит право собственности на монитор, и возобновит выполнение.

Как и в версии с одним аргументом, возможны прерывания и ложные пробуждения, и этот метод всегда должен использоваться в цикле:

synchronized (obj) {
   while (<условие не выполняется>)
       obj.wait();
   ... // Выполняем действие подходящее для условия
}

Этот метод должен вызываться только потоком, который является владельцем монитора этого объекта.

Выбрасываемые исключения:

IllegalMonitorStateException - если текущий поток не является владельцем монитора этого объекта.

InterruptedException - если какой-либо поток прерывал текущий поток до или в то время, когда текущий поток ожидал уведомления. Прерванное состояние текущего потока очищается при возникновении этого исключения.

Метод finalize

protected void finalize() throws Throwable

Вызывается сборщиком мусора на объекте, когда сборщик мусора определяет, что больше нет ссылок на объект. Подкласс переопределяет метод finalize для удаления системных ресурсов или для другой очистки.

Общий контракт finalize заключается в том, что он вызывается, если и когда виртуальная машина Java определила, что больше нет никаких средств, с помощью которых этот объект мог бы быть доступен любому потоку, который еще жив, кроме как в результате действия берется финализацией какого-то другого объекта или класса, который готов к финализации. Метод finalize может выполнять любые действия, включая повторное предоставление этого объекта другим потокам; однако обычная цель finalize - выполнить действия по очистке до того, как объект будет безвозвратно удален. Например, метод finalize для объекта, который представляет соединение ввода-вывода, может выполнять явные транзакции ввода-вывода, чтобы разорвать соединение до того, как объект будет окончательно удален.

Метод finalize класса Object не выполняет никаких специальных действий; он просто выполняет возврат. Подклассы Object могут переопределить это поведение.

Язык программирования Java не гарантирует, какой поток вызовет метод finalize для любого данного объекта. Однако гарантируется, что поток, который вызывает finalize, не будет удерживать видимые пользователем блокировки синхронизации, когда вызывается finalize. Если с помощью метода finalize генерируется неперехваченное исключение, оно игнорируется, и финализация этого объекта завершается.

После того, как метод finalize был вызван для объекта, никакие дальнейшие действия не предпринимаются, пока виртуальная машина Java снова не определит, что больше нет никаких средств, с помощью которых этот объект мог бы быть доступен любому потоку, который еще не жив, включая возможные действия другими объектами или классами, которые готовы к финализации, после чего объект может быть удален.

Метод finalize никогда не вызывается виртуальной машиной Java более одного раза для любого данного объекта.

Любое исключение, выброшенное методом finalize, приводит к остановке завершения этого объекта, но в противном случае игнорируется.

Выбрасываемые исключения:

Throwable - Exception, возбуждаемое этим методом

Комментарии

Популярные сообщения из этого блога

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки