java - 为什么这个 toString() 方法会导致 StackOverFlowError?
问题描述
我已经从这个和这个 答案中了解到,您的代码可能会进入无限循环导致 stackOverFlowError 但我不明白相同的场景是如何在这里复制的,
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 StackoverflowErrorTest {
public static void main(String[] args) {
A a = new A();
System.out.println(a);
}
}
此代码在堆栈跟踪下方生成:-
Exception in thread "main" java.lang.StackOverflowError
at stackoverflowerror.B.<init>(B.java:5)
at stackoverflowerror.A.<init>(A.java:5)
.
.
.
据我了解,当我在 main 方法中打印对象“a”时,它将调用 A 类的 toString 方法,在该方法中我返回 B 类的对象,该对象将隐式调用 B 类的 toString 方法。现在,在 B 类的 toString 方法中,我返回的只是一个空字符串。那么无限循环的范围是如何以及在哪里出现的。请解释。
解决方案
问题不在于toString
,而在于private B b = new B();
and private A a = new A();
。
您正在创建 A 创建 B 创建 A 创建 B 等等
和 stacktrace 说的完全相同:B.<init>
意味着初始化程序,而不是toString
. 它还指向您抛出异常的行:B.java:5
和A.java:5
实时代码:https ://ideone.com/H8wwOR
如果你真的需要坚持下去A
,B
你可以B
使用A
构造函数参数或通过 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);
这是一个简化的示例,因此您可以了解。在大型应用程序中,如果需要,您可能希望添加构建器、字段/构造函数参数注入或工厂。
推荐阅读
- excel - 工作簿的VBA条件格式零值字体颜色白色
- javascript - 如何从 Typeahead React 多选中删除一个项目?
- python - 使用来自不同数据集的 for 循环绘图
- authentication - Odoo 是否为其 API 实现了 oauth2?
- sql - 日期查询以选择当前月份的 1 日至 3 日并与列进行比较
- node.js - 将node.exe安装路径添加到环境变量路径中?
- r - 在 R 中跨两个数据帧生成重复的数据迭代
- azure - 将 Google Analytics 数据导入 Azure Blob/Data Lake 的最佳方式是什么?
- php - Laravel 5.8:电子邮件验证链接导致 403 错误
- excel - 如何将某个范围的值保存到变量中