同一个对象的所有 JVM 实现的输出是否Object.hashCode()
需要相同?
例如,如果在 1.4 上"test".hashCode()
返回1
,它可能会2
在 1.6 上返回运行。或者如果操作系统不同,或者实例之间有不同的处理器架构怎么办?
不会。 的输出hashCode
可能会在 JVM 实现之间甚至在同一 JVM 上程序的不同执行之间发生变化。
但是,在您给出的具体示例中,值"test".hashCode()
实际上是一致的,因为对象的实现hashCode
是String
API 的一部分String
(请参阅java.lang.String 的 Javadocs和其他 SO 帖子)。
从 API
hashCode 的一般合约是:
在合理可行的情况下,由 Object 类定义的 hashCode 方法确实为不同的对象返回不同的整数。(这通常通过将对象的内部地址转换为整数来实现,但 JavaTM 编程语言不需要这种实现技术。)
不, 的结果hashCode()
仅在单次执行期间保持不变。您不应该期望函数的结果在执行之间是相同的,更不用说在 JRE 版本或平台之间了。
首先,hashCode 的结果很大程度上取决于 Object 类型及其实现。每个类包括其子类都可以定义自己的行为。您可以按照 javadoc 以及其他答案中概述的一般合同来依赖它。但该值不需要在 VM 重新启动后保持不变。特别是如果它依赖于第三方类的 .hashCode 实现。
在提到 String 类的具体实现时,不要依赖返回值。如果您的程序在不同的 VM 中执行,它可能会发生变化。
如果您仅提及 Sun Vm,则可能会争辩说 Sun 不会破坏现有代码——即使是编程错误的代码。因此对于任何版本的 Sun VM,“test”.hashCode() 将始终准确返回 3556498。
如果您想故意向自己的脚开枪,请继续依靠这一点。需要修复在“2015 Nintendo Java VM for Hairdryer”上运行的代码的人会在晚上喊出你的名字。
如前所述,对于许多实现,hashCode() 的默认行为是返回对象的地址。显然,每次运行程序时,这可能会有所不同。这也与 equals() 的默认行为一致:两个对象只有当它们是同一个对象时才相等(其中 x 和 y 都是非空的,x.equals(y) 当且仅当 x == y 时) .
对于覆盖 hashCode() 和 equals() 的任何类,通常它们是基于部分或全部成员的值以确定性方式计算的。因此,在实践中,如果一个程序运行中的对象可以说与程序另一运行中的对象相等,并且源代码相同(包括诸如 String 的源代码之类的东西) .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(最快)
当哈希码等于堆中的地址时 - 这有时很尴尬,因为 GC 可以将对象移动到另一个堆单元等。