如果重新定义了 toString 方法,如何打印对象的地址

新手上路,请多包涵

我是 Java 的新手。现在我正在研究 equals 和 == 以及 equals 和 toString 的重新定义。

我想同时使用我重新定义的 toString 方法和从 Object 类继承的默认方法。

我没有使用那个超级修改器来达到那个方法。

这仅用于教育目的。如果您看一下我的代码中的注释,我想得到的会更清楚。

你能帮我吗?

我的代码是:

 public class EqualTest{
    public static void main(String[] args){
        Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15);
            //System.out.super.println(alice1);

        Employee alice2 = alice1;
            //System.out.super.println(alice2);

        Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15);
            //System.out.super.println(alice3);

        System.out.println("alice1==alice2: " + (alice1==alice2));
        System.out.println("alice1 == alice3: " + (alice1==alice3));
        System.out.println("alice1.equals(alice3): " + alice1.equals(alice3));
    }
}

class Employee{
...
    public String toString(){
        return getClass().getName() + "[name = " + name +
            ", salary=" + salary + ", hireDay=" + hireDay + "]";
    }

}

原文由 Kifsif 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 993
2 个回答

严格来说,您不能在纯 Java 中打印对象的地址。 Object.toString() 生成的字符串中看起来像对象地址的数字是对象的“身份哈希码”。它可能与对象的当前地址相关,也可能不相关:

  • 规范 没有 说明身份哈希码数字是如何计算的。它是故意未指定的。

  • 由于该数字是哈希码,因此 无法 更改。因此,即使它(通常)与对象地址相关,那也将 是第一次访问哈希码时 对象的地址。这可能与其当前地址不同,如果自从第一次观察对象的身份哈希码以来 GC 移动了该对象,它 也会 有所不同。

  • 在 64 位 JVM(具有足够大的堆大小/不使用压缩的 oops)上,地址将不适合作为 int 返回的身份哈希码编号。

无论如何,获取此号码的方法是致电 System.identityHashCode(obj)


如果你真的想要一个对象的 当前 地址,你可以使用 JNI 和本地方法(以及一些抽象中断),或者使用 Unsafe 类中的方法(参见 如何获取内存位置Java 中的对象? )。但请注意,这两种方法都是不可移植的。此外,当 GC 运行时,它们给你的对象地址很容易“中断”,这使得它们对于许多(可能是大多数)潜在用例来说都是有问题的。


对于怀疑者,这是 Java 10 javadocs 在“hashcode != address”点上所说的:

“(哈希码 可能会或可能不会 在某个时间点作为对象内存地址的 某些功能 来实现。)”

重点补充道。实际上,对于最近的 JVM,默认算法根本不从内存地址派生哈希码。至少从 Java 7 开始就是这样。

您可以通过在命令行选项中包含 -XX:+PrintFlagsFinal 来确认 hashcode 标志的默认值,然后查看 OpenJDK 源代码以了解其含义。 (该代码在某些版本中位于“vm/runtime/synchronizer.cpp”文件中,但 YMMV。)

原文由 Stephen C 发布,翻译遵循 CC BY-SA 4.0 许可协议

如果你想实现某种默认的 toString() 行为,你可以使用 System.identityHashCode() 方法。默认 toString() 将如下所示:

 public String toString(Object o) {
    return o.getClass().getName() + "@" +
           Integer.toHexString(System.identityHashCode(o));
}

原文由 Andrew Logvinov 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题