hashCode()和identityHashCode()如何在后端工作?

Him*_*shu 40 java object hashcode

如何做Object.hashCode()System.identityHashCode()工作在后端?是否identityHashCode()返回对象的引用?是否hashCode()取决于?对象?==运算符如何在后端工作.

hashCode()和之间有什么区别identityHashCode()

Ste*_*n C 32

Object.hashCode()和System.identityHashCode()如何在后端工作?

假设它没有被覆盖,该Object.hashCode()方法只是调用System.identityHashCode(this).

确切的行为System.identityHashCode(Object)取决于JVM实现.(最近的Hotspot JVM的实际实现相当聪明,但我离题了.)

是否identityHashCode()返回对象的引用?

不.它返回一个int,并且int不能保持参考.(咄!)

返回的整数identityHashCode可能与(a)对象的机器地址有关,也可能不是1.identityHashCode() 保证返回的值不会在对象的生命周期内更改.这意味着GC重新定位一个对象(在identityHashCode()调用之后),然后它不能使用新的对象地址作为标识哈希码.

hashCode()是否依赖于?对象? ==操作符如何在后端工作.

这没有意义.Java中没有? ==?==运算符.

hashCode()和identityHashCode()有什么区别?

以上部分解释了这一点.其他差异包括:

  • hashcode()方法是非最终实例方法,应该在被覆盖的任何类中equals(Object)重写.相比之下,identityHashCode(Object)是一种static方法,因此不能被覆盖.

  • identityHashCode(Object)方法为您提供了一个对象的标识符,该标识符可以(理论上)用于除散列和散列表之外的其他内容.(不幸的是,它不是一个独特的标识符,但保证从不为对象的生命周期变化).


1 - 对于当前生成的JVM,它根本与内存地址无关.请参阅@ bestsss的答案.


bes*_*sss 20

identityHashCode()的工作方式与此类似(截至目前,它没有任何关于地址的信息,特别是因为地址长度为64位,所以对齐,所以61)

检查是否已生成一个,如果是,则返回它.您可以假设对象标题中有一个位置int;

否则:生成一个随机数(iirc twister Marsaglia shift-xor算法),每个本机线程都有自己的种子,所以没有共享信息.CAS identityHashCode对象头中的字段用新生成的数字更新.如果CAS成功返回值,如果不是 - 该字段已包含已生成的值identityHashCode.

您可以看到有关覆盖哈希码的其余回复.

底线:如果javadoc仍然陈述有关地址和identityHashCode的任何内容,则有人需要更新它.

  • 代码中有 5 种哈希码计算的替代方案。看着 [this](http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/tip/src/share/vm/runtime/globals.hpp#l1148) 可以看到选项 5,Marsaglia shift-xor,目前确实在用。[这篇博文](https://srvaroa.github.io/jvm/java/openjdk/biased-locking/2017/01/30/hashCode.html)对Hashcode的生成进行了更详细的阐述 (2认同)

tem*_*def 11

这几乎是特定于实现的.你得到的唯一保证是

尽管合理可行,但是hashCode由class定义的方法Object确实为不同的对象返回不同的整数.(这通常通过将对象的内部地址转换为整数来实现,但Java TM编程语言不需要此实现技术.)

(来自Java 1.6 JavaDoc)

理论上,这意味着这些值可以任意确定,甚至可以为每个对象为零.在实践中,它可能是从对象的地址派生的东西.当然,你必须要小心这一点.如果JVM在垃圾收集期间认为它是个好主意,它可以重新定位对象,因此它不会"只是"内存地址.它可以从全局计数器,或原始对象的位置的散列,或从随机数生成器等中提取.

  • @ Himanshu-`Object.hashCode()`是`hashCode()`的默认实现,并且经常被派生类重写,以符合`equals()`/`hashCode()`的规则.`System.identityHashCode()`提供了一种方法来获取`Object.hashCode()`将为该对象返回的值,即使它包含此方法的覆盖.这允许您创建使用标识语义的容器,因为`==`和`System.identityHashCode()`唯一地处理每个对象. (8认同)

Hit*_*uge 9

上面已经回答了很多,补充几点。

当我们说obj.hashCode()考虑 obj 的内容时,另一方面,System.identityHashCode(obj)不考虑内容,因此identityHashCode对于两个不同的Stringint(具有相同值)将不同但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
Run Code Online (Sandbox Code Playgroud)

这里s1s3指向相同的引用,因此identityHashCodefors1 and s3总是相同的并且s2会有所不同。

同样intIntegerCache在获得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
Run Code Online (Sandbox Code Playgroud)


Vis*_*ant 5

身份哈希码

公共静态 int 身份HashCode(对象x)

为给定对象返回与默认方法 hashCode() 返回的哈希码相同的哈希码,无论给定对象的类是否覆盖 hashCode()。空引用的哈希码为零。

请参阅 [ Java 文档]

因此,如果有人在其类中重写了方法,但仍然想要由Object返回的hashCode()默认值,则使用hashCode() hashCode()System.identityHashCode()

因此,只要您不在类中重写它,hashCode()内部调用就会被调用,如果您重写 hashCode() ,它将调用您的实现。System.identityHashCode()