Как работают 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, а int не может содержать ссылку. (Duh!)

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

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

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

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

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

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

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


1 - For current generation JVMs, it is not related to the memory address at all. See @bestsss answer.

Ответ 2

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

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

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

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

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

Ответ 3

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

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

(из Java 1.6) Java

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

Ответ 4

identityHashCode

public static int identityHashCode (Object x)

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

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

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

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

Ответ 5

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

Когда мы говорим obj.hashCode(), содержимое объекта рассматривается, с другой стороны в 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