system.identityhashcode() 返回对象内存地址哈希,用于区分内容相同但不同实例的对象,调试、弱引用缓存、序列化验证及单元测试中识别同一实例时必须使用,但不保证唯一性,不能替代 == 判断同一性。

System.identityHashCode() 返回的是对象的内存地址哈希,不是 hashCode() 重写后的逻辑值——它在对象被 Object.hashCode() 重写后依然稳定,是调试、去重、识别“同一对象”时的关键工具。
什么时候必须用 System.identityHashCode() 而不是 hashCode()
当你需要区分“两个内容相同但不同实例”的对象时,hashCode() 可能返回一样(比如两个 new String("a")),而 System.identityHashCode() 一定不同(除非发生哈希码碰撞,极罕见)。
- 实现自定义弱引用缓存,靠原始哈希快速定位对象实例
- 排查集合中是否真的存了多个相同内容的对象(而非重复引用)
- 序列化/反序列化前后验证对象身份是否丢失(比如 JSON 库把对象转成 Map 再还原,原始身份已不可追溯)
- 单元测试里断言“这两个对象不是同一个实例”,又不想用
==(比如它们被封装在不同 wrapper 中)
System.identityHashCode() 的行为边界和陷阱
它不保证唯一性,只是基于对象头中存储的 identity hash 值(JVM 实现相关),且一旦对象被 GC 移动或锁升级,部分 JVM 可能会重新计算该值(HotSpot 在未锁状态下通常只计算一次)。
- 不要把它当 UUID 用:两个对象可能偶然返回相同值(概率低但存在)
- 对
null调用会抛NullPointerException,必须先判空 - 数组对象也支持,但
int[]和String[]的哈希互不干扰——别误以为“数组内容相同就哈希相同” - 子类重写了
hashCode()不影响它,但如果你在hashCode()里调用了System.identityHashCode(this),要注意这和直接调用不是完全等价(后者更早触发哈希生成)
和 ==、equals() 的关系怎么理清
System.identityHashCode() 是 == 的“轻量代理”:如果两个对象 ==,那它们的 identity hash 一定相等;但反过来不成立——哈希相等 ≠ 是同一对象。
立即学习“Java免费学习笔记(深入)”;
- 想快速排除“肯定不是同一对象”?先比哈希,不等就不用再
== - 想确认“一定是同一对象”?必须用
==,哈希只是线索 -
equals()完全无关:它走业务逻辑,identity hash 走 JVM 对象标识机制 - 典型误用:
if (System.identityHashCode(a) == System.identityHashCode(b)) { ... }当作a == b用——这是错的,可能漏判或误判
真正难的不是调用它,而是记住它只反映“某一时刻 JVM 认为的这个对象的身份快照”——没有运行时元数据支持,它就是个带偏移的地址摘要。用的时候,永远多留一层 == 校验,尤其在关键路径上。










