在 Java 程序里,我们常常需要区分两个引用是否指向同一个对象,或者想在日志里标记对象的身份。虽然 JVM 不允许直接读取对象的内存地址,但 System.identityHashCode() 提供了一个基于对象身份的哈希值,通常被视为对象的物理内存哈希值标识。

什么是 System.identityHashCode()
System.identityHashCode(Object x) 是 Java 标准库中的一个静态本地方法。它返回的是对象默认的哈希码,也就是在没有重写 hashCode() 时 Object 类所定义的那种哈希值。这个值在对象生命周期内保持不变,并且不同的对象通常会有不同的返回值。
与 hashCode() 的区别
如果某个类重写了 hashCode() 方法,调用该对象的 hashCode() 会执行业务逻辑;而 System.identityHashCode() 永远忽略重写,只看对象本身的身份哈希。
| 对比项 | hashCode() | System.identityHashCode() |
|---|---|---|
| 是否受重写影响 | 是 | 否 |
| 主要用途 | 逻辑相等判断 | 对象身份标识 |
| null 参数 | 不适用 | 返回 0 |
如何使用 System.identityHashCode()
下面通过一个简单示例展示如何获取并打印对象的身份哈希值:
public class IdentityHashDemo {
public static void main(String[] args) {
// 创建一个普通对象
Object objA = new Object();
Object objB = new Object();
// 利用 System.identityHashCode 获取身份哈希
int hashA = System.identityHashCode(objA);
int hashB = System.identityHashCode(objB);
System.out.println("objA 身份哈希: " + hashA);
System.out.println("objB 身份哈希: " + hashB);
System.out.println("是否为同一对象: " + (hashA == hashB));
// 即使类重写了 hashCode,identityHashCode 也不受影响
String s = new String("test");
System.out.println("String hashCode: " + s.hashCode());
System.out.println("String identityHashCode: " + System.identityHashCode(s));
}
}
处理 null 引用
当传入 null 时,System.identityHashCode(null) 会直接返回 0,不会抛出空指针异常。这点在写工具方法时很实用。
public static String tagOf(Object o) {
// null 对象返回固定标识,避免 NPE
if (o == null) {
return "null@0";
}
return o.getClass().getSimpleName() + "@" + System.identityHashCode(o);
}
典型应用场景
- 在调试日志中标记对象实例,确认两个变量是否指向同一块内存区域。
- 实现基于身份的缓存键,而不依赖业务字段。
- 排查 equals 和 hashCode 重写不当导致的集合异常。
注意事项
虽然 identityHashCode 常被称作物理内存哈希值标识,但它并不等于对象在堆中的真实地址。不同 JVM 实现可能采用不同算法生成该值,且哈希冲突在理论上依然存在。因此不要把它当作绝对唯一的全局 ID 使用。
总结:System.identityHashCode() 是 Java 中获取对象身份哈希的安全方式,适合需要绕开 hashCode 重写的场景,但应理解其局限,避免误用。
JavaSystem_identityHashCode对象哈希修改时间:2026-07-30 01:03:18