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

时间:2009-10-04 16:43:35

标签: java hashcode

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

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

6 个答案:

答案 0 :(得分:16)

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

但是,在您提供的具体示例中,"test".hashCode() 的值实际上是一致的,因为hashCode String对象的实现属于String的API(请参阅the Javadocs for java.lang.Stringthis other SO post)。

答案 1 :(得分:5)

来自API

hashCode的一般合约是:

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

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

答案 2 :(得分:3)

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

答案 3 :(得分:0)

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

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

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

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

答案 4 :(得分:0)

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

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

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

答案 5 :(得分:0)

唯一的事实: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(最快)

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