identityhashcode不能准确判定对象同一性,因哈希值不唯一、可能碰撞、jvm重用内存地址或优化导致变化;唯一可靠方式是使用==比较引用。
system.identityhashcode() 不能可靠判定两个对象是否为同一个原始实例,它只能作为**快速排除的辅助手段**,不能用于准确判断。
为什么 identityHashCode 不能准确判定同一性?
Java 规范明确指出:identityHashCode 的值不保证唯一,也不保证在对象生命周期内不变(尽管通常稳定)。关键点包括:
- 不同对象可能偶然产生相同的 identityHashCode(哈希碰撞),尤其在大量对象存在时;
- 该值本质是基于对象内存地址的某种映射,但 JVM 可能重用地址(如 GC 后对象被移动或复用内存块),导致新对象获得与旧对象相同的 identityHashCode;
- 某些 JVM 实现(如开启指针压缩或特定 GC 算法)可能进一步削弱其与真实地址的直接对应关系。
正确判定“是否为同一个原始实例”的唯一方式
必须使用 == 运算符,它直接比较对象引用(即内存地址):
-
a == b返回true⇨ 二者指向堆中同一块内存地址 ⇨ 是同一个实例; -
a == b返回false⇨ 二者指向不同地址 ⇨ 不是同一个实例(无论内容、类、hashCode 是否相同)。
这是 JVM 层面定义的严格同一性(identity),不可替代。
identityHashCode 的合理用途
它适合用于需要“稳定哈希值”的场景,且允许少量冲突,例如:
- 实现基于对象身份的弱缓存(如
WeakHashMap内部使用); - 调试时快速观察对象是否大概率被重复创建(配合日志或监控);
- 在无法修改类源码、又需区分不同实例的临时工具逻辑中作初步筛选(但后续仍需 == 确认)。
实际验证示例
以下代码可直观说明问题:
Object a = new Object(); Object b = new Object(); System.out.println(a == b); // false —— 正确判定非同一实例 System.out.println(System.identityHashCode(a) == System.identityHashCode(b)); // 可能为 true!
运行多次,你很可能遇到后一行输出 true 的情况——这恰恰证明:相同 identityHashCode ≠ 同一实例。










