Object.hashCode()
和System.identityHashCode()
如何在后端工作? identityHashCode()
是否返回对象的引用? hashCode()
是否取决于?对象? ==操作员如何在后端工作。
hashCode()
和identityHashCode()
之间有什么区别?
答案 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)
中不考虑内容,因此对于两个不同的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
的{{1}}始终相同,而s1 and s3
将不同。
与s2
相同,int
在获得IntegerCache
方面也起着重要的作用
identityHashCode