当toString()和hashCode()被覆盖时,如何获取java中对象的"对象引用"?

Nic*_*lai 100 java object hashcode

我想在Java中打印对象的"对象引用"以进行调试.即根据情况确保对象是相同的(或不同的).

问题是有问题的类继承自另一个类,它覆盖了toString()和hashCode(),它们通常会给我id.

示例情况:运行多线程应用程序,其中我(在开发期间)想要检查所有线程是否使用相同的资源对象实例.

Tof*_*eer 102

你打算用它做什么(你想做什么会影响你需要调用的东西).

hashCode,如JavaDocs中所定义,表示:

尽可能合理,Object类定义的hashCode方法确实为不同的对象返回不同的整数.(这通常通过将对象的内部地址转换为整数来实现,但Java™编程语言不需要此实现技术.)

因此,如果您正在使用它hashCode()来查明它是否是内存中的唯一对象,那么这不是一个好方法.

System.identityHashCode 执行以下操作:

返回给定对象的相同哈希码,就像默认方法hashCode()返回的一样,无论给定对象的类是否覆盖hashCode().空引用的哈希码为零.

对于你正在做的事情,听起来像你想要的......但是你想要做的事情可能不安全,这取决于库的实现方式.

  • 我没有按照代码中的值进行操作.作为公关.我的问题编辑,我只用它来调试某种情况.这就是为什么我觉得我的答案是合理的,但我给你一个+1的回答. (6认同)

Nic*_*lai 48

这就是我解决它的方式:

Integer.toHexString(System.identityHashCode(object));
Run Code Online (Sandbox Code Playgroud)

  • 这实际上并不正确,因为多个对象可以返回相同的identityHashCode. (5认同)
  • 不,这不是真的.这很可能,但不能保证,因为规范没有定义算法. (3认同)
  • 具有相同标识哈希的两个对象(引用)是否是同一个对象不是真的吗?那就是OP想要的东西 (2认同)

noa*_*hlz 8

==无论对象的hashCode或equals的实现如何,Double equals 将始终基于对象标识进行检查.当然 - 确保您正在比较的对象引用volatile(在1.5+ JVM中).

如果你真的必须拥有原始的Object toString结果(虽然它不是你的示例用例的最佳解决方案),Commons Lang库有一个方法ObjectUtils.identityToString(Object)可以做你想要的.来自JavaDoc:

public static java.lang.String identityToString(java.lang.Object object)
Run Code Online (Sandbox Code Playgroud)

如果类没有覆盖toString本身,则获取由Object生成的toString.null将返回null.

 ObjectUtils.identityToString(null)         = null
 ObjectUtils.identityToString("")           = "java.lang.String@1e23"
 ObjectUtils.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
Run Code Online (Sandbox Code Playgroud)

  • 此代码基于`identityHashCode`. (6认同)
  • 如果您使用的是 Java 7,那么您应该考虑使用 [java.util.Objects](http://docs.oracle.com/javase/7/docs/api/java/util/Objects.html) (2认同)
  • 关于您的评论,您想到了“java.util.Objects”中的什么方法?`Objects.toString(o)` 相当于调用 o.toString(),带有 null 检查,这似乎与这个问题无关。 (2认同)

Rob*_*bin 5

您不能安全地做您想做的事,因为默认的 hashCode() 可能不会返回地址,并且已经提到,多个对象可能具有相同的 hashCode。实现您想要的唯一方法是实际覆盖相关对象的 hashCode() 方法并保证它们都提供唯一值。这在您的情况下是否可行是另一个问题。

作为记录,我在 WAS 服务器中运行的 IBM VM 中遇到了多个具有相同默认哈希码的对象。我们有一个缺陷,即放入远程缓存的对象会因此被覆盖。这让我大开眼界,因为我假设默认的哈希码也是对象内存地址。