【发布时间】:2012-08-02 04:21:36
【问题描述】:
我知道 hashmap 键应该是不可变对象,或者至少具有一致的 hashcode 才能从 Map/Set 中正确检索其值。但是,如果我使用变异对象作为键而不覆盖哈希码或等于,它的哈希码是否会与它的生命周期一致。我已经尝试用它来检索变异对象的哈希码,并且发现它始终是一致的。
【问题讨论】:
我知道 hashmap 键应该是不可变对象,或者至少具有一致的 hashcode 才能从 Map/Set 中正确检索其值。但是,如果我使用变异对象作为键而不覆盖哈希码或等于,它的哈希码是否会与它的生命周期一致。我已经尝试用它来检索变异对象的哈希码,并且发现它始终是一致的。
【问题讨论】:
每当在 Java 应用程序执行期间对同一个对象多次调用时,hashCode 方法必须始终返回相同的整数,前提是没有修改对象上的 equals 比较中使用的信息.
因此,如果您改变对象,则无法保证哈希码不会改变。碰巧一些 JDK 实现可能会使用某种内部地址 but they don't have to,所以你不应该依赖它。
【讨论】:
在最新版本的 HotSpot JVM 中,对象的默认哈希码不会随时间改变。实际上,哈希码是从初始分配地址派生出来的,并随着对象被垃圾收集器移动而输入到对象头中(参见JVM Whitepaper),之后不会改变。
【讨论】:
hashcode的默认Java实现是基于指向对象的指针,所以当实例变量改变时它不应该改变。
编辑
但是 Martijn 打败了我。
【讨论】:
是的,如果您不覆盖 hashCode 方法,它将保持不变。默认的 hashCode 是对象在内存中的原始位置。此内存位置通过此方法检索:
System.identityHashCode(Object)
在 StackOverflow 上查看此线程:
How does the JVM ensure that System.identityHashCode() will never change?
【讨论】: