Как работают 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
метод, определенный classObject
, возвращает разные целые числа для разных объектов. (Обычно это реализуется путем преобразования внутреннего адреса объекта в целое число, но этот метод реализации не требуется для языка программирования 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