object.hashcode() 默认返回对象的身份标识(identity hash code),由jvm在首次调用时生成并缓存于对象头mark word中,与内存地址相关但不等同,确保同一对象多次调用结果一致且稳定,符合equals()默认引用相等的合约要求。

Java 中 Object.hashCode() 的默认实现,本质上是返回对象在 JVM 内存中的**身份标识(identity hash code)**,而非基于对象内容计算得出的值。它与对象的内存地址有关,但不等于地址本身——JVM 通常通过特定算法(如取地址的低位、扰动、或结合线程局部状态)生成一个 32 位整数,确保同一对象在生命周期内多次调用返回相同值,且不同对象尽量不冲突。
它不是直接返回内存地址
现代 JVM(如 HotSpot)不会直接把对象的内存地址转成 int 返回,原因有二:一是 64 位系统中地址可能超出 int 范围;二是地址可能被压缩(如开启 UseCompressedOops),且 GC 过程中对象会被移动,地址会变,而 hashCode 必须稳定。因此 JVM 在对象头(mark word)中预留空间,首次调用 hashCode() 时生成并缓存该值。
首次调用才生成,之后复用
这个 identity hash code 是懒加载的:
- 第一次调用
obj.hashCode()且未重写时,JVM 计算并写入对象头的 mark word - 后续调用直接读取缓存值,不再重新计算
- 即使对象被 GC 移动(如 G1 或 ZGC 的并发移动),只要对象还存活,缓存的 hash 值保持不变
与 equals() 的约定关系
默认 hashCode() 配合的是 Object.equals() 的默认行为(即 == 判断引用相等)。因此天然满足 hashCode() 合约:
- 同一对象多次调用返回相同值
- 若
a.equals(b)为 true,则a.hashCode() == b.hashCode()(因为默认 equals 为 ==,意味着 a 和 b 是同一对象,自然 hash 相同) - 若两个对象不相等,默认 hash 可能相同(碰撞),但 JVM 会尽量降低概率
子类重写时需同步维护一致性
一旦类重写了 equals()(比如按字段比较),就必须重写 hashCode(),否则会破坏合约。例如:










