118

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

问题是有问题的类继承自另一个类,该类已经覆盖了 toString() 和 hashCode() 这通常会给我 id。

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

4

6 回答 6

115

你到底打算用它做什么(你想做的事情与你需要打电话的事情不同)。

hashCode,如 JavaDocs 中所定义,说:

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

因此,如果您hashCode()要确定它是否是内存中的唯一对象,那么这不是一个好方法。

System.identityHashCode执行以下操作:

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

对于您正在做的事情,这听起来像是您想要的……但是您想要做的事情可能并不安全,具体取决于库的实现方式。

于 2009-02-24T09:07:08.273 回答
55

这就是我解决它的方法:

Integer.toHexString(System.identityHashCode(object));
于 2009-02-24T08:54:07.820 回答
9

无论对象的 hashCode 或 equals 实现如何,双等号==始终会根据对象身份进行检查。当然 - 确保您正在比较的对象引用是volatile(在 1.5+ JVM 中)。

如果您真的必须拥有原始的 Object toString 结果(尽管它不是您的示例用例的最佳解决方案),Commons Lang 库有一个方法ObjectUtils.identityToString(Object) 可以满足您的需求。来自 JavaDoc:

public static java.lang.String identityToString(java.lang.Object object)

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

 ObjectUtils.identityToString(null)         = null
 ObjectUtils.identityToString("")           = "java.lang.String@1e23"
 ObjectUtils.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
于 2009-02-25T04:01:48.343 回答
5

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

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

于 2009-02-24T14:58:07.277 回答
3

为所有实例添加唯一 ID,即

public interface Idable {
  int id();
}

public class IdGenerator {
  private static int id = 0;
  public static synchronized int generate() { return id++; }
}

public abstract class AbstractSomething implements Idable {
  private int id;
  public AbstractSomething () {
    this.id = IdGenerator.generate();
  }
  public int id() { return id; }
}

从 AbstractSomething 扩展并查询此属性。在单个虚拟机内将是安全的(假设没有使用类加载器玩游戏来绕过静态)。

于 2009-02-24T18:31:46.153 回答
1

我们可以简单地从对象类的tostring中复制代码来获取string的引用

class Test
{
  public static void main(String args[])
  {
    String a="nikhil";     // it stores in String constant pool
    String s=new String("nikhil");    //with new stores in heap
    System.out.println(Integer.toHexString(System.identityHashCode(a)));
    System.out.println(Integer.toHexString(System.identityHashCode(s)));
  }
}
于 2015-05-21T11:59:54.260 回答