我们知道在Java在所有类的父类是Object,容器自然也不例外。因此容器都有toString()方法,并且覆写了该方法,使容器生成的String结果能够表达容器自身,以及容器所有包含的对象。例如ArrayList的toString()方法,它会遍历ArrayList中包含的所有对象,调用每个对象的toString()方法。
如果你希望toString()方法打印出对象的内存地址,也许会考虑使用this关键字。 来看下面代码:
class User {
@Override
public String toString() {
return "User{}" + this;
}
}
public class TestMain {
public static void main(String[] args) {
List<User> users = new ArrayList<User>();
for (int i = 0; i < 10; i++)
users.add(new User());
System.out.println(users);
}
}
如果你只是简单的创建User对象,并打印出来,会得到非常长的异常,在上面代码中,把User对象加入到容器中,然后打印改ArrayList容器,会得到同样的异常。
Exception in thread "main" java.lang.StackOverflowError
at java.lang.AbstractStringBuilder.<init>(AbstractStringBuilder.java:63)
at java.lang.StringBuilder.<init>(StringBuilder.java:85)
at com.gthree.java.User.toString(TestMain.java:15)
at java.lang.String.valueOf(String.java:2847)
at java.lang.StringBuilder.append(StringBuilder.java:128)
at com.zjiajun.java.User.toString(TestMain.java:15)
at java.lang.String.valueOf(String.java:2847)
at java.lang.StringBuilder.append(StringBuilder.java:128)
关键就在于“User{}” + this,这里发生了自动类型转换,由User类型转换成String类型。编译器看到一个String对象后面跟着一个“+”(重载操作符,一个操作符在应用于特定的类时,被赋予了特殊的意义。在java中,用于String的“+”和“+=”是java中仅有的两个重载操作符),而再后面不是String,于是编译器试着将this转换成一个String。它怎么转换呢?正是通过调用this上的toString()方法,于是就发生了递归调用。 如果真的想打印出对象的内存地址,应该调用Object.toString()方法。所以不应该使用this,而是应该调用super.toString()方法。
class User {
@Override
public String toString() {
return "User{}" + super.toString();
}
}
[User{}com.gthree.java.User@5c1d29c1, User{}com.zjiajun.java.User@7ea06d25,......]
其实不用覆写User的toString()方法,也会打印出内存地址,默认使用的Object的toString()方法。
评论区