【发布时间】:2020-09-20 15:42:21
【问题描述】:
我正在学习 Java 记录、预览功能,并且在运行以下代码时遇到 StackOverflow 异常。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Example {
public record Course(String name, Student topper) { }
public record Student(String name, List<Course> enrolled) {}
public static void main(String[] args) {
Student john = new Student("John", new ArrayList<>());
john.enrolled().add(new Course("Enrolled for Math", john));
john.enrolled().add(new Course("Enrolled for History", john));
System.out.println(john);
}
}
Below is the exception trace :
java --enable-preview Example
Exception in thread "main" java.lang.StackOverflowError
at Example$Course.toString(Example.java:6)
at java.base/java.lang.String.valueOf(String.java:3388)
at java.base/java.lang.StringBuilder.append(StringBuilder.java:167)
at java.base/java.util.AbstractCollection.toString(AbstractCollection.java:457)
从异常中我意识到它与 toString() 有关,当我在记录中覆盖 toString() 时,如下代码所示,我没有看到异常。
// code with implementation of toString()
public class Example {
public record Course(String name, Student topper) {
public String toString()
{
return name;
}
}
public record Student(String name, List<Course> enrolled) {
public String toString()
{
return this.name+" : "+enrolled.stream().map(s->s.toString()).collect(Collectors.joining(","));
}
}
public static void main(String... args) {
Student john = new Student("John", new ArrayList<>());
john.enrolled().add(new Course("Enrolled for Math", john));
john.enrolled().add(new Course("Enrolled for History", john));
System.out.println(john);
}
}
此代码打印 John : Enrolled for Math,Enrolled for History 。有人可以解释为什么如果我不覆盖 toString() 我会得到 StackOverflow?当我打印 john.hashCode()
【问题讨论】:
-
与
hashCode()和equals()相同。 -
请注意,没有记录很容易构造相同的问题。
var x = new ArrayList(); var y = new ArrayList(); x.add(y); y.add(x),然后在x或y上调用toString()。在存在周期的情况下,几乎没有“不错的”toString()方法可以免受 SOE 的影响。
标签: java stack-overflow tostring java-14 java-record