问题描述
- 关于String中的一个递归问题
-
今天学习java String时,遇到书上讲的一个递归问题,先上代码
import java.util.*;
public class InfiniteRecursion {public String toStirng() { return "InfiniteRecursion address: "+ this +"n"; } public static void main(String[] args) { List<InfiniteRecursion> list = new ArrayList<InfiniteRecursion>(); for(int i = 0; i <2; i++) list.add(new InfiniteRecursion()); System.out.println(list); }
}
书上讲到在toString()方法里面,编译器会将this转化为String,而转换时会调用toString()方法,这样就产生了递归调用。。我思考了也这么觉得,,但是运行代码时没有报错。把this换成super.toString()也能运行。求请教,为什么没有递归(书上讲的java SE5,我的编译器是1.7的)。
解决方案
不会递归。因为你重写的是InfiniteRecursion的toString,而你调用的是List<InfiniteRecursion>
的toString
解决方案二:
这么写才会递归调用
package string;
public class InfiniteRecursion {
@Override
public String toString() {
//this关键字会调用this.toString()方法,产生递归
//修改为super.toString()
return "InfiniteRecursion : " + this;
}
public static void main(String[] args) {
InfiniteRecursion ir = new InfiniteRecursion();
System.out.println(ir.toString()); //Exception in thread "main" java.lang.StackOverflowError
}
}
解决方案三:
不会调用toString
http://ideone.com/cffA6l
返回的是类名@引用地址
解决方案四:
import java.util.*;
class Ideone {
public String toStirng() {
return "InfiniteRecursion address: "+ this +"n";
}
public static void main(String[] args) {
List<Ideone> list = new ArrayList<Ideone>();
for(int i = 0; i <2; i++)
list.add(new Ideone());
System.out.println(list);
}
}
在线编译运行结果
[Ideone@b8fba5, Ideone@9133f6]
解决方案五:
我的测试代码:
public static void main(String[] args) {
EverhThingTest ett = new EverhThingTest();
ett.printList();
// ett.printAbclr();
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "ssss"+this+"n";
}
private void printList() {
// TODO Auto-generated method stub
List<EverhThingTest> list = new ArrayList<EverhThingTest>();
list.add(new EverhThingTest());
list.add(new EverhThingTest());
System.out.println(list);
}
你这个问题确实很有意思,建议你在输出时打个断点跟一下,我根据你的代码测试了一下,我这里是可以递归调用,程序没有结果,会报Exception in thread "main" java.lang.StackOverflowError。从下面的错误信息可以看到递归调用了,如下:
Exception in thread "main" java.lang.StackOverflowError
at java.lang.System.arraycopy(Native Method)
at java.lang.String.getChars(String.java:854)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:391)
at java.lang.StringBuilder.append(StringBuilder.java:119)
at java.lang.StringBuilder.<init>(StringBuilder.java:93)
at EverhThingTest.toString(EverhThingTest.java:16)
at java.lang.String.valueOf(String.java:2826)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at EverhThingTest.toString(EverhThingTest.java:16)
at java.lang.String.valueOf(String.java:2826)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at EverhThingTest.toString(EverhThingTest.java:16)
at java.lang.String.valueOf(String.java:2826)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at EverhThingTest.toString(EverhThingTest.java:16)
at java.lang.String.valueOf(String.java:2826)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at EverhThingTest.toString(EverhThingTest.java:16)
at java.lang.String.valueOf(String.java:2826)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at EverhThingTest.toString(EverhThingTest.java:16)
at java.lang.String.valueOf(String.java:2826)
后面还有...
我在JDK1.6和1.7上都试过了,都是不可以的。不知道你的1.7为啥不能递归调用。
顺便说一下,输出list时,调用的toString方法在AbstractCollection类中(我两次跟代码都是跟到了这里,你自己看下是不是一致),代码如下:
public String toString() {
Iterator<E> it = iterator();
if (! it.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
上面的sb.append(e == this ? "(this Collection)" : e);语句中,会调用StingBuilder的append(Object obj)方法,代码如下:
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
而上面的String.valueOf(obj)方法的代码如下:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
可以看到,最终还是指向了obj的toString方法,也就是你自己定义的toString方法。
建议你断点调试下,看看问题所在,期待你的回复。
解决方案六:
刚才那个确实没有调用InfiniteRecursion的toString()方法,但是现在这个是调用了RecursionTest的toString()方法。而且也发生了递归。
import java.util.ArrayList;
import java.util.List;
class RecursionTest {
public String toString() {
System.out.println("this is called");
return "recursion: "+this;
}
}
public class Test {
public static void main(String[] args) {
List<RecursionTest> lr = new ArrayList<RecursionTest>();
lr.add(new RecursionTest());
System.out.println(lr);
}
}
解决方案七:
统一回复一下,我把toString()方法名写错了,并没有调用我的这个方法,所以最终还是会调用toString()的,也产生了递归了。