System.identityHashCode() 返回对象JVM层面的唯一标识哈希值,不受equals/hashCode重写影响,用于区分逻辑相等与同一实例;典型场景包括调试集合去重、引用敏感缓存及排查对象共享;对null返回0,值稳定不变,但不可替代==判断,需配合使用以确保准确性。

System.identityHashCode() 的作用是返回对象的底层内存地址哈希值(JVM 层面的 identity hash),它**不受 equals() 或 hashCode() 重写影响**。当你需要区分“逻辑相等”和“实际是同一个对象实例”时,这个方法就非常关键。
为什么需要 identityHashCode 来排除 equals 干扰
如果一个类重写了 equals()(比如 String、Integer、自定义 POJO),那么两个不同对象可能 equals() 返回 true,但它们是独立创建的、内存地址不同的实例。此时用普通 hashCode() 无法可靠区分——因为按约定,重写 equals() 通常也要重写 hashCode(),导致逻辑相等的对象也返回相同哈希值。
System.identityHashCode() 绕过所有 Java 层逻辑,直接读取对象的 JVM identity hash(与 == 判定同一性的依据一致),因此能真实反映“是不是同一个对象”。
典型使用场景:判断是否为同一实例而非逻辑相等
-
调试集合去重逻辑:比如你怀疑
Set因重写hashCode()出现误合并,可用System.identityHashCode(obj)打印每个元素的 identity 值,确认它们是否真为不同对象。 -
实现引用敏感缓存或代理:当缓存键需严格基于对象身份(如 AOP 代理、弱引用监听),不能接受
equals()带来的模糊性,此时用identityHashCode+==双重校验更安全。 -
排查意外的对象共享:比如多个模块传入看似相同的
new User("Alice"),但你怀疑某处复用了同一实例,打印其identityHashCode可快速验证。
怎么正确使用(注意边界)
-
System.identityHashCode(obj)对null安全,返回 0 —— 但要注意这和其他非空对象的返回值不冲突(JVM 保证非空对象 identity hash ≠ 0)。 - 它**不能替代
==做相等判断**:两个不同对象可能偶然有相同 identity hash(虽然概率极低,尤其在小堆中),所以严谨场景下应配合==使用,例如:if (a == b || (a != null && b != null && System.identityHashCode(a) == System.identityHashCode(b))) { ... }
实际中,若只需快速区分,单独用identityHashCode已足够;若需 100% 确保是同一实例,必须用a == b。 - 该值在对象生命周期内**稳定不变**(即使发生 GC 移动,JVM 会维护 identity hash 不变),可放心用于日志、临时标记或调试。
对比示例(代码片段示意)
假设:
User u1 = new User("Tom", 25);
User u2 = new User("Tom", 25); // 内容相同,但新实例
User u3 = u1; // 同一引用
且 User 重写了 equals() 和 hashCode():
-
u1.equals(u2)→true -
u1.hashCode() == u2.hashCode()→true -
System.identityHashCode(u1) == System.identityHashCode(u2)→false(大概率) -
System.identityHashCode(u1) == System.identityHashCode(u3)→true










