为什么这个 toString() 方法会导致 StackOverFlowError?
Why is this toString() method causing StackOverFlowError?
我从this and this了解到
回答,您的代码可能进入无限循环导致 WhosebugError 的可能情况,但我不明白如何在此处复制相同的情况,
public class A {
private B b = new B();
@Override
public String toString() {
return "b "+b;
}
}
public class B {
private A a = new A();
@Override
public String toString() {
return "";
}
}
public class WhosebugErrorTest {
public static void main(String[] args) {
A a = new A();
System.out.println(a);
}
}
此代码生成的堆栈跟踪如下:-
Exception in thread "main" java.lang.WhosebugError
at Whosebugerror.B.<init>(B.java:5)
at Whosebugerror.A.<init>(A.java:5)
.
.
.
据我了解,当我在 main 方法中打印对象 'a' 时,它将调用 A class 的 toString 方法,在该方法中我返回 B class 这将隐式调用 B class 的 toString 方法。现在,在 B class 的 toString 方法中,我返回的只是一个空字符串。那么无限循环的范围如何以及在哪里出现在这里。请解释。
当你在 main 中调用 A a = new A();
时,代码将调用 A 的构造函数,后者将调用 private B b = new B();
,后者将调用 private A a = new A();
等等无限循环: )
问题与 toString()
完全无关
它进入了事件的无限循环。在这种情况下,方法 toString()
是无辜的:
- 方法
main
创建 class A
的实例
- class
A
在初始化时创建 class B
的实例
- class
B
在初始化时创建 class A
的实例
- 转到步骤
2
局部变量分配在堆栈上,WhosebugError
是错误递归调用的结果。
Thrown when a stack overflow occurs because an application recurses too deeply.
推荐的解决方案,删除class B
中对class A
的引用,因为它未被使用:
public class B {
@Override
public String toString() {
return "";
}
}
问题不在于 toString
,而在于 private B b = new B();
和 private A a = new A();
。
您正在创建 A,创建 B,创建 A,创建 B,依此类推
stacktrace 说的完全一样:B.<init>
表示初始值设定项,而不是 toString
。它还指向抛出异常的行:B.java:5
和 A.java:5
实时代码:https://ideone.com/H8wwOR
如果您确实需要在 B
中保留 A
并在 A
中保留 B
您可以使用构造函数参数或通过 setter 方法传递它们:
class A {
private B b;
public A(B b) {
this.b = b;
}
}
class B {
private A a;
public A getA() {
return this.a;
}
public void setA(A a) {
this.a = a;
}
}
然后像这样使用它们:
B b = new B();
A a = new A(b);
b.setA(a);
这是一个简化的示例,您可以了解一下。在大型应用程序中,如果需要,您可能希望添加构建器、字段/构造函数参数注入或工厂。
每个 A
在其 b
字段中包含一个新的 B
。每个 B
在其 a
字段中包含一个新的 A
。
创建一个新的 A
会自动创建一个新的 B
,创建 that 会自动创建另一个新的 A
,另一个新的 B
,以此类推,直到堆栈溢出。
你的A包含B,A包含B,A包含B,A包含B,A包含B,A包含B,A包含B,A包含B,A包含B,A包含B ....
您在 B 中的 A 未被使用,因此您可以将其删除。
注意:堆栈跟踪显示问题出在构造中,即 () 与您的 toString() 无关;
在这种情况下,每当您创建 class A(或 B)的对象时,它也会在实例化时创建 class B(或 A,如果是 B)的新对象。现在这是一个永无止境的循环,因为无论何时创建 class A 或 B 的新对象,都会再次创建另一个 class 的新对象,从而导致对象创建的无限循环。因此,抛出 java.lang.WhosebugError 异常。
我从this and this了解到 回答,您的代码可能进入无限循环导致 WhosebugError 的可能情况,但我不明白如何在此处复制相同的情况,
public class A {
private B b = new B();
@Override
public String toString() {
return "b "+b;
}
}
public class B {
private A a = new A();
@Override
public String toString() {
return "";
}
}
public class WhosebugErrorTest {
public static void main(String[] args) {
A a = new A();
System.out.println(a);
}
}
此代码生成的堆栈跟踪如下:-
Exception in thread "main" java.lang.WhosebugError
at Whosebugerror.B.<init>(B.java:5)
at Whosebugerror.A.<init>(A.java:5)
.
.
.
据我了解,当我在 main 方法中打印对象 'a' 时,它将调用 A class 的 toString 方法,在该方法中我返回 B class 这将隐式调用 B class 的 toString 方法。现在,在 B class 的 toString 方法中,我返回的只是一个空字符串。那么无限循环的范围如何以及在哪里出现在这里。请解释。
当你在 main 中调用 A a = new A();
时,代码将调用 A 的构造函数,后者将调用 private B b = new B();
,后者将调用 private A a = new A();
等等无限循环: )
问题与 toString()
完全无关
它进入了事件的无限循环。在这种情况下,方法 toString()
是无辜的:
- 方法
main
创建 classA
的实例
- class
A
在初始化时创建 classB
的实例 - class
B
在初始化时创建 classA
的实例 - 转到步骤
2
局部变量分配在堆栈上,WhosebugError
是错误递归调用的结果。
Thrown when a stack overflow occurs because an application recurses too deeply.
推荐的解决方案,删除class B
中对class A
的引用,因为它未被使用:
public class B {
@Override
public String toString() {
return "";
}
}
问题不在于 toString
,而在于 private B b = new B();
和 private A a = new A();
。
您正在创建 A,创建 B,创建 A,创建 B,依此类推
stacktrace 说的完全一样:B.<init>
表示初始值设定项,而不是 toString
。它还指向抛出异常的行:B.java:5
和 A.java:5
实时代码:https://ideone.com/H8wwOR
如果您确实需要在 B
中保留 A
并在 A
中保留 B
您可以使用构造函数参数或通过 setter 方法传递它们:
class A {
private B b;
public A(B b) {
this.b = b;
}
}
class B {
private A a;
public A getA() {
return this.a;
}
public void setA(A a) {
this.a = a;
}
}
然后像这样使用它们:
B b = new B();
A a = new A(b);
b.setA(a);
这是一个简化的示例,您可以了解一下。在大型应用程序中,如果需要,您可能希望添加构建器、字段/构造函数参数注入或工厂。
每个 A
在其 b
字段中包含一个新的 B
。每个 B
在其 a
字段中包含一个新的 A
。
创建一个新的 A
会自动创建一个新的 B
,创建 that 会自动创建另一个新的 A
,另一个新的 B
,以此类推,直到堆栈溢出。
你的A包含B,A包含B,A包含B,A包含B,A包含B,A包含B,A包含B,A包含B,A包含B,A包含B ....
您在 B 中的 A 未被使用,因此您可以将其删除。
注意:堆栈跟踪显示问题出在构造中,即 () 与您的 toString() 无关;
在这种情况下,每当您创建 class A(或 B)的对象时,它也会在实例化时创建 class B(或 A,如果是 B)的新对象。现在这是一个永无止境的循环,因为无论何时创建 class A 或 B 的新对象,都会再次创建另一个 class 的新对象,从而导致对象创建的无限循环。因此,抛出 java.lang.WhosebugError 异常。