hashCode()和identityHashCode()如何在后端工作?
Object.hashCode()
和System.identityHashCode()
如何在后端工作? identityHashCode()
是否返回对象的引用? hashCode()
是否依赖于? 的对象? ==运营商如何在后端工作。
hashCode()和identityHashCode()之间有什么区别?
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()
方法是一个非final实例方法,应该在equals(Object)
被覆盖的任何类中重写。 相比之下,identityHashCode(Object)
是一个static
方法,因此不能被覆盖。 -
identityHashCode(Object)
方法为您提供了一个对象的标识符,它可以(理论上)用于哈希表和散列表之外的其他事物。 (不幸的是,它不是一个唯一的标识符,但它保证永远不会改变对象的生命周期。)
1 – 对于当代的JVM,根本不涉及内存地址。 请参阅@ bestsss的答案。
identityHashCode()是这样工作的( 到目前为止,它没有任何地址,尤其是因为地址是64位长,所以alignment,所以61 )
检查是否已经生成了一个,如果是,则返回。 你可以假设在这个int
的对象头部有一个地方;
否则:生成一个随机数( iirc twister Marsaglia shift-xoralgorithm),每个本地线程都有自己的种子,所以没有共享信息。 CAS对象头中的identityHashCode
字段用来更新新生成的数字。 如果CAS成功返回值,如果不成功 – 则该字段已包含生成的identityHashCode
。
你可以看到关于重写hashcode的其他回复。
底线:如果javadoc仍然陈述有关地址和identityHashCode的任何信息,则有人需要更新它。
这几乎是特定于实现的。 你得到的唯一保证是
尽可能多地合理实用,由类
Object
定义的hashCode
方法确实为不同的对象返回不同的整数。 (这通常通过将对象的内部地址转换为整数来实现,但Java TM编程语言不需要此实现技术。)
(来自Java 1.6的JavaDoc)
从理论上讲,这意味着价值可以任意确定,甚至可以为每个对象为零。 在实践中,它可能是从对象的地址派生的东西。 当然,你必须小心这个。 如果JVM在垃圾收集过程中认为这是一个好主意,那么它可以重定位对象,所以它不会只是内存地址。 它可以从全局计数器或原始对象的位置或从随机数生成器等获得。
identityHashCode
public static int identityHashCode(Object x)
无论给定对象的类是否覆盖hashCode() ,都将返回给定对象的哈希码,与默认方法hashCode()返回的哈希码相同 。 空引用的散列码为零。
请参阅[ Java文档 ]
因此,如果有人在其类中重写了hashCode()
方法,但仍然希望使用Object hashCode()
返回的默认hashCode()
值,则使用System.identityHashCode()
所以, hashCode()
内部调用System.identityHashCode()
,只要你不覆盖它在你的类,如果你重写hashCode()它会调用你的实现。