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

时间:2011-02-08 08:00:57

标签: java object hashcode

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

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

5 个答案:

答案 0 :(得分:26)

  

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的答案。

答案 1 :(得分:18)

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

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

的位置

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

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

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

答案 2 :(得分:11)

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

  

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

(来自Java 1.6 JavaDoc)

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

答案 3 :(得分:2)

  

identityHashCode

     

public static int identityHashCode(Object x)

     

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

见[Java docs]

因此,如果有人在其类中覆盖了hashCode()方法,但仍希望使用 Object hashCode()返回的默认hashCode()值,则使用{ {1}}

所以,System.identityHashCode()内部调用hashCode() ,只要你没有覆盖你的类,如果你覆盖hashCode()它会调用你的实现。

答案 4 :(得分:0)

上面给出的很多答案,只需添加一些要点即可。

另一方面,当我们说obj.hashCode()时,会考虑obj的内容 在System.identityHashCode(obj)中不考虑内容,因此对于两个不同的identityHashCodeString(具有相同值)的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

此处s1s3指向相同的引用,因此identityHashCode的{​​{1}}始终相同,而s1 and s3将不同。

s2相同,int在获得IntegerCache方面也起着重要的作用

identityHashCode