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

标签 java

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

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

我没有使用那个 super 修饰符来达到那个方法。

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

你能帮帮我吗?

我的代码是:

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 + "]";
    }

}

最佳答案

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

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

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

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

总之,得到这个号码的方法是调用System.identityHashCode(obj) .


如果你真的想要一个对象的当前地址,你可以使用 JNI 和一个本地方法(以及一些抽象中断),或者使用 Unsafe 中的方法来获取它类(见 How can I get the memory location of a object in java?)。但请注意,这两种方法都是不可移植的。此外,当 GC 运行时,它们提供给您的对象地址可能会“中断”,这使得它们对于许多(可能是大多数)潜在用例来说都是有问题的。


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

"(The hashCode may or may not be implemented as some function of an object's memory address at some point in time.)"

添加了重点。实际上,对于最近的 JVM,默认算法根本不会从内存地址派生 hashCode。至少从 Java 7 开始就是这样。

您可以通过在命令行选项中包含 -XX:+PrintFlagsFinal 来确认这一点,以找出 hashcode 标志的默认值,然后查看 OpenJDK 源代码代码看看是什么意思。 (代码在某些版本的“vm/runtime/synchronizer.cpp”文件中,但是YMMV。)

关于java - 如果重新定义了 toString 方法,如何打印对象的地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18396927/

相关文章:

java - 如何连接到具有不同 IP 地址的网站?

java - JDBC 在 "same"时间打开 2 个连接

java - 树条件中的一次查询

java - 多个 Camel 路由会导致线程数量非常多吗?

java - JasperException(找不到文件)随机发生

java - 设置 spinners onResume 不起作用

java - 垃圾收集似乎在 Java 中不起作用

java - 找到未排序数组中所有缺失数字的最快方法是什么

java - "No qualifying bean of type"用于 Spring Boot 中的 JPA 存储库

java - 使给定字符串成为回文