所有JVM /系统中的Java,Object.hashCode()结果常量?

Object.hashCode()的输出是否必须在同一个对象的所有JVM实现上相同?

例如,如果"test".hashCode()在1.4上返回1 ,它是否可能在1.6上返回2 。 或者,如果操作系统不同,或者实例之间存在不同的处理器架构,该怎么办?

hashCode的输出在JVM实现之间甚至在同一JVM上的程序的不同执行之间也可能发生变化。

但是,在您给出的具体示例中, "test".hashCode()的值实际上是一致的,因为String对象的hashCode的实现是String的API的一部分(请参阅java.lang.String的Javadocs和this其他SOpost )。

来自API

hashCode的一般契约是:

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

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

不, hashCode()的结果在单次执行期间保持不变。 您不应期望函数的结果在执行之间是相同的,更不用说在JRE版本或平台之间。

首先,hashCode的结果在很大程度上取决于Object类型及其实现。 包括其子类在内的每个类都可以定义自己的行为。 您可以按照javadoc以及其他答案中概述的一般合同来依赖它。 但VM重启后,该值不需要保持不变。 特别是如果它依赖于第三方类的.hashCode实现。

在引用String类的具体实现时,不应该依赖返回值。 如果您的程序在另一个VM中执行,则可能会发生变化。

如果你只提到Sun Vm,可以说Sun不会破坏 – 甚至编程错误 – 现有的代码。 所以“test”.hashCode()将始终为任何版本的Sun VM返回3556498

如果你想在脚下射击自己,请继续依靠这个。 那些需要修复在“2015 Nintendo Java VM for Hairdryer”上运行的代码的人会在晚上叫出你的名字。

如上所述,对于许多实现,hashCode()的默认行为是返回对象的地址。 显然,每次运行程序时都会有所不同。 这也与equals()的默认行为一致:两个对象只有在它们是同一个对象时才相等(其中x和y都是非null,x.equals(y)当且仅当x == y时) 。

对于覆盖hashCode()和equals()的任何类,通常它们是基于某些或所有成员的值以确定的方式计算的。 因此,实际上很可能如果程序的一次运行中的对象可以说等于程序的另一次运行中的对象,并且源代码是相同的(包括诸如String的源代码之类的东西) .hashCode()如果由hashCode()覆盖调用,则哈希码将是相同的。

尽管很难想出一个合理的现实世界的例子,但这并不能保证。

唯一的事实是:hashcode与应用程序运行相同。 另一个运行可能会给出其他的哈希码。

当您请求对象的哈希码时,JVM使用RNG算法之一创建它并将其放入对象的头部以供将来使用。 只需查看OpenJDK中的get_next_hash函数即可。

RNG算法可配置为JVM arg -XX:hashCode = x ,其中x是数字:

0 – Park-Miller RNG(默认)

1 – f(地址,全球)

2 – 常数1

3 – 顺序计数器

4 – 堆中的对象地址

5 – Xorshift(最快)

当hashcode等于堆中的地址时 – 这有时很尴尬,因为GC可以将对象移动到另一个堆单元等。