72

通常,默认实现Object.hashCode()是内存中对象的分配地址的某些功能(尽管JLS没有强制要求)。鉴于虚拟机在内存中分流对象,为什么System.identityHashCode()在对象的生命周期内返回的值从不改变?

如果它是“一次性”计算(对象的hashCode计算一次并隐藏在对象头或其他东西中),那么这是否意味着两个对象有可能具有相同的identityHashCode(如果它们恰好在内存中的相同地址)?

4

5 回答 5

42

现代 JVM 将值保存在对象标头中。我相信该值通常仅在首次使用时计算,以便将对象分配所花费的时间保持在最低限度(有时低至十几个周期)。可以编译通用的 Sun JVM,以便所有对象的标识哈希码始终为 1。

多个对象可以具有相同的身份哈希码。这就是哈希码的本质。

于 2009-06-30T11:09:16.920 回答
16

在回答第二个问题时,无论实现如何,多个对象都可能具有相同的 identityHashCode。

有关javadoc 中措辞的简要讨论,以及演示非唯一性的程序,请参见错误 6321873 。

于 2009-06-30T11:08:56.733 回答
2

HotSpot 中对象的头部由一个类指针和一个“标记”字组成。

标记词的数据结构的源代码可以在该markOop.hpp文件中找到。在这个文件中,有一条注释描述了标记词的内存布局:

hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)

在这里我们可以看到,32 位系统上普通 Java 对象的身份哈希码保存在标记字中,长度为 25 位。

于 2015-06-12T20:29:15.067 回答
0

实现散列函数的一般准则是:

  • 同一个对象应该返回一致的 hashCode,它不应该随时间变化或依赖于任何可变信息(例如,由随机数或可变成员字段值播种的算法
  • 哈希函数应该具有良好的随机分布,我的意思是,如果您将哈希码视为存储桶,则 2 个对象应尽可能映射到不同的存储桶(哈希码)。2 个对象具有相同哈希码的可能性应该很少 - 尽管它可能发生。
于 2009-06-30T11:14:04.820 回答
-4

据我所知,这是为了返回引用而实现的,它在对象生命周期中永远不会改变。

于 2009-06-30T11:07:26.063 回答