我想在 Java 中打印对象的“对象引用”以进行调试。即根据情况确保对象相同(或不同)。
问题是有问题的类继承自另一个类,该类已经覆盖了 toString() 和 hashCode() 这通常会给我 id。
示例情况:运行多线程应用程序,我(在开发期间)想检查所有线程是否使用资源对象的相同实例。
你到底打算用它做什么(你想做的事情与你需要打电话的事情不同)。
hashCode
,如 JavaDocs 中所定义,说:
在合理可行的情况下,由 Object 类定义的 hashCode 方法确实为不同的对象返回不同的整数。(这通常通过将对象的内部地址转换为整数来实现,但 Java™ 编程语言不需要这种实现技术。)
因此,如果您hashCode()
要确定它是否是内存中的唯一对象,那么这不是一个好方法。
System.identityHashCode
执行以下操作:
为给定对象返回与默认方法 hashCode() 返回的相同的哈希码,无论给定对象的类是否覆盖 hashCode()。空引用的哈希码为零。
对于您正在做的事情,这听起来像是您想要的……但是您想要做的事情可能并不安全,具体取决于库的实现方式。
这就是我解决它的方法:
Integer.toHexString(System.identityHashCode(object));
无论对象的 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"
你不能安全地做你想做的事,因为默认的 hashCode() 可能不会返回地址,并且已经提到,具有相同 hashCode 的多个对象是可能的。完成您想要的唯一方法是实际覆盖所讨论对象的 hashCode() 方法并保证它们都提供唯一值。这在您的情况下是否可行是另一个问题。
作为记录,我在 WAS 服务器中运行的 IBM VM 中经历了多个具有相同默认哈希码的对象。我们有一个缺陷,即被放入远程缓存的对象会因此而被覆盖。这让我大开眼界,因为我假设默认的哈希码也是对象的内存地址。
为所有实例添加唯一 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 扩展并查询此属性。在单个虚拟机内将是安全的(假设没有使用类加载器玩游戏来绕过静态)。
我们可以简单地从对象类的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)));
}
}