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()它会调用你的实现。