Вопрос-ответ

How do hashCode() and identityHashCode() work at the back end?

Как работают hashCode() и identityHashCode() на серверной части?

Как Object.hashCode() и System.identityHashCode() работают на серверной части? identityHashCode() Возвращает ссылку на объект? hashCode() Зависит ли это от содержимого или адреса объекта?

В чем разница между hashCode() и identityHashCode()?

Переведено автоматически
Ответ 1

Как Object.hashCode() и System.identityHashCode() работают на серверной части?


Предполагая, что он не был переопределен, Object.hashCode() метод просто вызывает System.identityHashCode(this).

Точное поведение System.identityHashCode(Object) зависит от реализации JVM. (Фактическая реализация на последних JVM Hotspot довольно умна, но я отвлекся.)


identityHashCode() Возвращает ссылку на объект?


Нет. Он возвращает int, а an int не может содержать ссылку.

Это целое число, возвращаемое identityHashCode может быть связано с (a) машинным адресом объекта, или оно может не быть1. Значение, возвращаемое с помощью identityHashCode() гарантированно не изменится в течение всего срока службы объекта. Это означает, что если GC перемещает объект (после identityHashCode() вызова), то он не может использовать новый адрес объекта в качестве хэш-кода идентификатора.


Зависит ли hashCode() от оператора ? объекта ? ==, как работать на серверной части.


Это не имеет смысла. В Java нет оператора ? == or ?==.


В чем разница между hashCode() и identityHashCode()?


Это частично объяснено выше. Другие отличия включают:


  • hashCode()Метод не являетсяfinal методом экземпляра и должен быть переопределен в любом классе, где equals(Object) переопределен. В отличие от этого, identityHashCode(Object) является static методом и, следовательно, не может быть переопределен.



  • Метод identityHashCode(Object) дает вам идентификатор объекта, который (теоретически) можно использовать для других целей, помимо хеширования и хэш-таблиц. (К сожалению, это не уникальный идентификатор, но он гарантированно никогда не изменится в течение всего срока службы объекта.)




1 - Для JVM текущего поколения это вообще не связано с адресом памяти. Смотрите Ответ @bestsss .

Ответ 2

identityHashCode() работает подобным образом (и на данный момент это не имеет никакого отношения к адресу, тем более что адреса имеют длину 64 бита, выровнены нормально, поэтому 61):

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

В противном случае: Генерирует случайное число (алгоритм Marsaglia shift-xor). Каждый собственный поток имеет собственное начальное значение, поэтому никакой общей информации. ИСПОЛЬЗУЕТ identityHashCode поле в заголовке объекта для обновления с новым сгенерированным номером. Если CAS завершается успешно, возвращает значение. Если нет, поле уже содержит сгенерированный identityHashCode.

Вы можете просмотреть остальные ответы о переопределении hashcode.

Итог: если JavaDoc по-прежнему указывает что-либо об адресах и identityHashCode, кому-то нужно это обновить.

Ответ 3

Это в значительной степени зависит от реализации. Единственная гарантия, которую вы получаете, это


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


(Из Java 1.6 JavaDoc)

Теоретически это означает, что значения могут быть определены произвольно и даже могут быть равны нулю для каждого объекта. На практике, вероятно, это что-то производное от адреса объекта. Конечно, с этим нужно быть осторожным. JVM может перемещать объекты, если сочтет это хорошей идеей во время сборки мусора, поэтому это не будет "просто" адрес памяти. Это может быть получено из глобального счетчика, или хэша местоположения исходного объекта, или из генератора случайных чисел, и т.д.

Ответ 4

Множество ответов приведено выше, просто нужно добавить несколько моментов.

Когда мы говорим, что obj.hashCode() рассматривается содержимое объекта obj, с другой стороны, в System.identityHashCode(obj) содержимое не принимается во внимание, таким образом, identityHashCode для двух разных String, int (с одинаковым значением) будет разным, но Hashcode будет одинаковым.

В случае String получения identityHashCode пула строк важную роль играет, например

    Object s1 = "abcd";
Object s2 = new String("abcd");
Object s3 = "abcd";
System.out.println("identityHashCode : " + System.identityHashCode(s1) + " HashCode : " + s1.hashCode());
System.out.println("identityHashCode : " + System.identityHashCode(s2) + " HashCode : " + s2.hashCode());
System.out.println("identityHashCode : " + System.identityHashCode(s3) + " HashCode : " + s3.hashCode());

//output:
identityHashCode : 2018699554 HashCode : 2987074
identityHashCode : 1311053135 HashCode : 2987074
identityHashCode : 2018699554 HashCode : 2987074

здесь s1 и s3 поэтому указание одного и того же ref identityHashCode для s1 and s3 всегда одно и то же и s2 будет отличаться.

То же самое для int также, IntegerCache играет важную роль для получения identityHashCode

    Object s1 = 5;
Object s2 = new Integer(5);
Object s3 = 5;
System.out.println("identityHashCode : " + System.identityHashCode(s1) + " HashCode : " + s1.hashCode());
System.out.println("identityHashCode : " + System.identityHashCode(s2) + " HashCode : " + s2.hashCode());
System.out.println("identityHashCode : " + System.identityHashCode(s3) + " HashCode : " + s3.hashCode());

//Output
identityHashCode : 2018699554 HashCode : 5
identityHashCode : 1311053135 HashCode : 5
identityHashCode : 2018699554 HashCode : 5
java