System.identityHashCode() 返回对象唯一稳定的身份标识而非真实内存地址,因JVM为安全、GC移动性及跨平台性不暴露原始地址;它与equals/hashCode无关,即使对象被移动或类重写hashCode也保持不变。

System.identityHashCode() 并不返回对象在堆内存中的“原始地址”(如 C 中的指针值),而是返回 JVM 为该对象分配的一个**唯一、稳定、与 equals/hashCode 无关的整数标识**,其底层通常基于对象的内存地址生成,但经过哈希运算和平台适配,**不可用于指针操作或内存寻址**。
它为什么不是真实内存地址?
JVM(尤其是 HotSpot)出于安全、GC 移动性(如压缩指针、对象重定位)、跨平台一致性等考虑,从不向 Java 程序暴露原始内存地址。identityHashCode 是一个“逻辑身份码”,即使对象被 GC 移动,只要未被回收,它的 identityHashCode 在整个生命周期内保持不变。
例如:
Object obj = new Object();int hash1 = System.identityHashCode(obj);
// 经历一次 Full GC 后(对象仍存活)
int hash2 = System.identityHashCode(obj);
// hash1 == hash2 一定为 true
它和普通 hashCode() 的核心区别
-
普通 hashCode():由类重写决定,语义上应与
equals()一致;若未重写,则默认行为与identityHashCode()相同(但不保证) -
identityHashCode():始终与对象身份绑定,不受
equals()或hashCode()重写影响;即使对象类重写了hashCode()返回固定值(如return 42;),System.identityHashCode(obj)仍返回其唯一身份码
典型使用场景
-
实现“基于身份”的哈希容器:如
IdentityHashMap内部就依赖identityHashCode和 == 判断键 -
调试与日志中区分同一类型的不同实例:尤其在对象重写了
toString()或hashCode()导致难以分辨时,打印System.identityHashCode(obj)可快速识别是否为同一对象 - 避免 equals 语义干扰的临时去重:例如在遍历过程中需按“物理实例”去重,而非逻辑相等(如两个内容相同但不同 new 出来的 String)
注意事项
- 返回值是
int,存在哈希冲突可能(不同对象偶然得到相同 identityHashCode),因此不能用它做唯一性断言的唯一依据,必须配合==运算符验证 - null 值调用会抛
NullPointerException,使用前需判空 - 对数组也有效:
System.identityHashCode(new int[10])返回该数组对象的身份码,而非其元素内容的哈希
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











