Java 如果重新定义了 toString 方法,如何打印对象的地址
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18396927/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to print the address of an object if you have redefined toString method
提问by Kifsif
I'm a newbie to Java. Now I'm studying equals and == and redefinition of equals and toString.
我是 Java 的新手。现在我正在研究 equals 和 == 以及 equals 和 toString 的重新定义。
I would like to use both the toString method that I have redefied and the default method that is inherited from the Object class.
我想同时使用我重新定义的 toString 方法和从 Object 类继承的默认方法。
I failed to use that super modificator to reach that method.
我没有使用那个超级修饰符来达到那个方法。
This is for educational purposes only. What I would like to get is more clear if you will have a look at the comments in my code.
这仅用于教育目的。如果您查看我代码中的注释,我想得到的会更清楚。
Could you help me here?
你能帮我吗?
My code is:
我的代码是:
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 + "]";
}
}
采纳答案by Stephen C
Strictly speaking, you can't print the address of an object in pure Java. The number that looks like an object address in the String produced by Object.toString()
is the object's "identity hashcode". It may or may not be related to the object's current address:
严格来说,不能在纯 Java 中打印对象的地址。生成的字符串中看起来像对象地址的数字Object.toString()
是对象的“身份哈希码”。它可能与对象的当前地址有关,也可能无关:
The specs do not sayhow the identity hashcode number is calculated. It is deliberately left unspecified.
Since the number is a hashcode, it cannotchange. So even though it is (typically) related to an object address, that will be the object's address at the time when the hashcode was first accessed. This could be different to its current address, and it willbe different if the GC has moved the object since the first time the object's identity hashcode was observed.
On a 64bit JVM (with a large enough heap size / not using compressed oops) addresses won't fit into an identity hashcode number which is returned as an
int
.
规范没有说明如何计算身份哈希码。它是故意未指定的。
由于数字是哈希码,因此无法更改。因此,即使它(通常)与对象地址相关,也将是第一次访问哈希码时的对象地址。这可能与它的当前地址不同,如果 GC 自从第一次观察到对象的身份哈希码以来就移动了该对象,则情况会有所不同。
在 64 位 JVM(具有足够大的堆大小/不使用压缩 oops)上,地址不适合作为
int
.
Anyhow, the way to get this number is to call System.identityHashCode(obj)
.
无论如何,获得这个号码的方法是调用System.identityHashCode(obj)
.
If you really want an object's current address, you can get it using JNI and a native method (and some abstraction breaking), or by using methods in the Unsafe
class. But beware that both of these approaches are non-portable ... and that the object addresses that they give you are liable to "break" when the GC runs.
如果你真的想要一个对象的当前地址,你可以使用 JNI 和本地方法(和一些抽象破坏),或者通过使用Unsafe
类中的方法来获取它。但是请注意,这两种方法都是不可移植的……并且它们提供给您的对象地址在 GC 运行时可能会“中断”。
For the doubters, this is what the Java 10 javadocs say on the "hashcode != address" point:
对于怀疑者,这就是 Java 10 javadocs 在“hashcode != address”点上所说的:
"(The hashCode may or may notbe implemented as some function ofan object's memory address at some point in time.)"
“(hashCode可能会也可能不会被实现为某个时间点对象内存地址的某个函数。)”
Emphasis added. Indeed, with recent JVMs, the default behavior is to NOT base the hashCode on a memory address at all. It has been that way since at least Java 7.
加了重点。事实上,对于最近的 JVM,默认行为是根本不将 hashCode 基于内存地址。至少从 Java 7 开始就是这样。
You can confirm this by including -XX:+PrintFlagsFinal
to find out what the hashcode
flag defaults to, and then looking at the OpenJDK source code to see what it means. (The code is in the "vm/runtime/synchronizer.cpp" file in some versions, but YMMV.)
您可以通过包含-XX:+PrintFlagsFinal
来确定hashcode
标志的默认值来确认这一点,然后查看 OpenJDK 源代码以了解其含义。(代码在某些版本的“vm/runtime/synchronizer.cpp”文件中,但YMMV。)
回答by Aniket Thakur
You can call super() method to execute the corresponding superclass method.
您可以调用 super() 方法来执行相应的超类方法。
class Employee{
...
public String toString(){
String s = super.toString();
return getClass().getName() + "[name = " + name +
", salary=" + salary + ", hireDay=" + hireDay + "]" + s;
}
toString() in Object class is as follows
Object类中的toString()如下
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
回答by Scary Wombat
Here is an in-depth answer about overriding equals and hashcode
这是关于覆盖 equals 和 hashcode 的深入答案
What issues should be considered when overriding equals and hashCode in Java?
在 Java 中重写 equals 和 hashCode 时应该考虑哪些问题?
The key point being The relation between the two methods is:
关键是这两种方法之间的关系是:
Whenever a.equals(b), then a.hashCode() must be same as b.hashCode().
每当 a.equals(b) 时,a.hashCode() 必须与 b.hashCode() 相同。
回答by Andrew Logvinov
If you want to achieve sort-of default toString()
behavior, you can make use of System.identityHashCode()
method. Default toString()
will then look like this:
如果要实现某种默认toString()
行为,可以使用System.identityHashCode()
方法。默认toString()
将如下所示:
public String toString(Object o) {
return o.getClass().getName() + "@" +
Integer.toHexString(System.identityHashCode(o));
}
回答by Alexey Odintsov
You may create another method inside your Employee class to use super toString method.
您可以在 Employee 类中创建另一个方法来使用 super toString 方法。
See example:
见示例:
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());
}
}
or combine both in one method:
或将两者结合在一种方法中:
public class Employee {
public String toString() {
return super.toString() + " MyToStringMethod";
}
public static void main(String[] args) {
Employee b = new Employee();
System.out.println(b);
}
}