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

Kif*_*sif 40 java

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

}
Run Code Online (Sandbox Code Playgroud)

Ste*_*n C 72

严格来说,您无法在纯Java中打印对象的地址.在生成的String中看起来像对象地址的数字Object.toString()是对象的"身份哈希码".它可能与对象的当前地址有关,也可能与之无关:

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

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

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

无论如何,获得这个号码的方法是打电话System.identityHashCode(obj).


如果你真的想要一个对象的当前地址,你可以使用JNI和本机方法(以及一些抽象破坏),或者通过使用Unsafe类中的方法来获取它.但请注意,这两种方法都是不可移植的......并且当GC运行时,它们给你的对象地址可能会"破坏".


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

"(hashCode 可能会或可能不会在某个时间点实现为对象的内存地址的某些功能.)"

强调补充说.实际上,对于最近的JVM,默认行为是根本不将hashCode基于内存地址.至少从Java 7开始就是这样.

你可以通过包括-XX:+PrintFlagsFinal找出hashcode标志默认的内容来确认这一点,然后查看OpenJDK源代码以了解它的含义.(代码在某些版本的"vm/runtime/synchronizer.cpp"文件中,但是YMMV.)


And*_*nov 16

如果要实现排序默认toString()行为,可以使用System.identityHashCode()方法.默认toString()将如下所示:

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