Как hashCode () и identityHashCode () работают на серверной части? - PullRequest
36 голосов
/ 08 февраля 2011

Как Object.hashCode() и System.identityHashCode() работают на заднем конце? identityHashCode() возвращает ссылку на объект? hashCode() зависит от? объекта? == оператор как работать в бэк-энде.

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

Ответы [ 5 ]

27 голосов
/ 08 февраля 2011

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

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

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

Возвращает ли * 1013 ссылку на объект?

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

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

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

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

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

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

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

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


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

18 голосов
/ 08 февраля 2011

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

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

в противном случае: генерирует случайное число (алгоритм iirc twister Marsaglia shift-xor ), каждый собственный поток имеет свое начальное число, поэтому нет общей информации. CAS поле identityHashCode в заголовке объекта для обновления с вновь созданным номером. если CAS success возвращает значение, если нет - поле уже содержит сгенерированный identityHashCode.

Вы можете увидеть остальные ответы о переопределении хэш-кода.

Нижняя строка: если Javadoc все еще заявляет что-либо об адресах и identityHashCode, кто-то должен обновить его.

11 голосов
/ 08 февраля 2011

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

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

(ИзJava 1.6 JavaDoc)

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

2 голосов
/ 30 марта 2017

identityHashCode

public static int identityHashCode (Object x)

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

См. [ Документы Java ]

Так что если кто-то переопределил метод hashCode() в своем классе, но все жехотите значение hashCode() по умолчанию, которое было бы возвращено Object hashCode(), затем используйте System.identityHashCode()

Итак, hashCode() внутренне вызывает System.identityHashCode() до тех пор, пока вы не переопределите его в своем классе, если вы переопределите hashCode (), он будет вызывать вашу реализацию.

0 голосов
/ 15 сентября 2018

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

Когда мы говорим 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, указывающие одну и ту же ссылку, поэтому 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
...