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

时间:2013-08-23 07:08:50

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

}

5 个答案:

答案 0 :(得分:57)

严格地说,您无法在纯Java中打印对象的地址。在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。)

答案 1 :(得分:13)

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

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

答案 2 :(得分:0)

您可以调用super()方法来执行相应的超类方法。

class Employee{
...
    public String toString(){
         String s = super.toString();
        return getClass().getName() + "[name = " + name + 
            ", salary=" + salary + ", hireDay=" + hireDay + "]" + s;
    }
Object类中的

toString()如下

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

答案 3 :(得分:0)

这是关于覆盖equals和hashcode的深入解答

What issues should be considered when overriding equals and hashCode in Java?

关键点在于 这两种方法之间的关系是:

每当a.equals(b),a.hashCode()必须与b.hashCode()相同。

答案 4 :(得分:0)

您可以在Employee类中创建另一个方法来使用super toString方法。

参见示例:

public class Employee {
    public String toString() {
        return "MyToStringMethod";
    }

    public String superToString() {
        return super.toString();
    }

    public static void main(String[] args) {
        Employee b = new Employee();
        System.out.println(b);
        System.out.println(b.superToString());
    }
}

或将两者合并为一种方法:

public class Employee {
    public String toString() {
        return super.toString() + " MyToStringMethod";
    }

    public static void main(String[] args) {
        Employee b = new Employee();
        System.out.println(b);
    }
}