如果没有覆盖hashCode(),那么对象的哈希码是什么?

jav*_*eek 63 java object hashcode

如果没有覆盖hashCode()方法,那么在Java中的任何对象上调用hashCode()的结果是什么?

Tag*_*eev 54

在HotSpot JVM中默认情况下首次调用非重载Object.hashCodeSystem.identityHashCode生成一个随机数并存储在对象头中.随后调用Object.hashCodeSystem.identityHashCode仅从标头中提取此值.默认情况下,它与对象内容或对象位置没有任何共同之处,只是随机数.此行为由-XX:hashCode=nHotSpot JVM选项控制,该选项具有以下可能的值:

  • 0:使用全局随机生成器.这是Java 7中的默认设置.它的缺点是来自多个线程的并发调用可能会导致竞争条件,这将导致为不同的对象生成相同的hashCode.此外,在高度并发的环境中,由于争用(使用来自不同CPU核心的相同内存区域),可能会出现延迟.
  • 5:使用一些没有先前缺点的线程局部xor-shift随机发生器.这是Java 8中的默认设置.
  • 1:使用对象指针混合了一些在"stop-the-world"事件上改变的随机值,因此在stop-the-world事件(如垃圾收集)之间生成的hashCodes是稳定的(用于测试/调试目的)
  • 2:始终使用1(用于测试/调试目的)
  • 3:使用自动增量数字(用于测试/调试目的,也使用全局计数器,因此争用和竞争条件是可能的)
  • 4:如有必要,使用对象指针修剪为32位(用于测试/调试目的)

请注意,即使您设置-XX:hashCode=4,hashCode也不会始终指向对象地址.可以稍后移动对象,但hashCode将保持不变.此外,对象地址的分布也很差(如果您的应用程序使用的内存不多,大多数对象将彼此靠近),因此如果使用此选项,最终可能会出现不平衡的哈希表.


Han*_*s W 35

通常,如果不覆盖它,hashCode()只返回内存中对象的地址.

1开始:

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

  • 我强烈反对"转换内部地址",我一直想知道Sun/Oracle是否会从他们的javadoc中删除该行.无法保证对象的内部地址在JVM中保持不变,JVM的垃圾收集器可能会在堆压缩期间移动它. (17认同)
  • JavaDoc引用是正确的,但答案不是.对象的地址多年未使用. (17认同)

Asa*_*aph 13

实施hashCode()可能因类不同而不同,但合同hashCode()非常具体,并在Javadocs中明确和明确地说明:

返回对象的哈希码值.支持此方法是为了哈希表的好处,例如java.util.Hashtable提供的哈希表.

hashCode的一般契约是:

  • 每当在执行Java应用程序期间多次在同一对象上调用它时,hashCode方法必须始终返回相同的整数,前提是不修改对象上的equals比较中使用的信息.从应用程序的一次执行到同一应用程序的另一次执行,该整数不需要保持一致.
  • 如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须生成相同的整数结果.
  • 如果两个对象根据equals(java.lang.Object)方法不相等,则不需要在两个对象中的每一个上调用hashCode方法必须生成不同的整数结果.但是,程序员应该知道为不等对象生成不同的整数结果可能会提高哈希表的性能.

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

hashCode()紧密相关equals(),如果你覆盖equals(),你也应该覆盖hashCode().

  • "hashCode()与equals()密切相关,如果你实现了一个,你应该实现另一个"并不完全正确.如果重写equals,则只需覆盖hashCode.在不覆盖equals的情况下覆盖hashCode在技术上是有效的. (2认同)