首页 > 解决方案 > 为什么这个 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 方法中,我返回的只是一个空字符串。那么无限循环的范围是如何以及在哪里出现的。请解释。

标签: javastack-overflow

解决方案


问题不在于toString,而在于private B b = new B();and private A a = new A();

您正在创建 A 创建 B 创建 A 创建 B 等等

和 stacktrace 说的完全相同:B.<init>意味着初始化程序,而不是toString. 它还指向您抛出异常的行:B.java:5A.java:5

实时代码:https ://ideone.com/H8wwOR

如果你真的需要坚持下去AB你可以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);

这是一个简化的示例,因此您可以了解。在大型应用程序中,如果需要,您可能希望添加构建器、字段/构造函数参数注入或工厂。


推荐阅读