我当时正在阅读Java 8集合接口文档。我注意到Java 8采集接口在Java 7采集接口中没有包含的描述中添加了这个段落。
对集合直接或间接包含的自引用实例,执行递归遍历集合的某些集合操作可能会失败。这包括克隆()、等于()、hashCode()和toString()方法。实现可以选择性地处理自引用场景,但大多数当前实现不这样做。
我有点搞不懂为什么会包括这一段。是因为Java 7不能有直接或间接包含自己的自引用实例吗?然后Java 8引入了新的接口或一些新的特性,允许这样做吗?
我正在寻找详细的解释,如果你包括一个例子来说明你的观点,那就太好了。
发布于 2017-08-17 19:52:17
是因为Java7不能有直接或间接包含自己的自引用实例吗?然后,Java8引入了新的接口或者允许这样做的一些新特性?
我不这样认为。
当然,在Java 8之前,实例可能具有自引用。
当然,在Collection中使用它们可以在运行时创建无限循环和失败,并引发一个StackOverflowError。
这里有两个类,其中实例字段之间有循环依赖关系,每个类的toString()方法依赖于它们自己的字段。
指子女的父母:
public class Parent {
private List<Child> childs;
public Parent(List<Child> childs) {
this.childs = childs;
}
@Override
public String toString() {
return "Parent [childs=" + childs + "]";
}
}指父母的子女:
public class Child {
private Parent parent;
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
@Override
public String toString() {
return "Child [parent=" + parent + "]";
}
}假设现在您创建了一个Child和一个关联的父级:
List<Child> childs = new ArrayList<>();
Child child = new Child();
childs.add(child);
Parent parent = new Parent(childs);
child.setParent(parent);现在您可以调用:
parent.toString();
child.toString();或者在Collection实例上,例如:
childs.toString();您将得到完全相同的结果:java.lang.StackOverflowError
当子调用父级的父级时,调用父级,以此类推。
文档很可能是用Java 8更新的,以强制以脆弱的方式实现这些方法的风险,因为Collection实现通常不处理这些方法,而且隐藏被窃听的客户端代码的故障是有意义的,否则问题就永远解决不了。
“实现可以选择性地处理自引用场景,但大多数当前实现不这样做。”
发布于 2017-08-17 19:49:34
为List指定了List格式;它必须递归地对内容进行toString(),并在由[ ... ]分隔的逗号分隔的列表中呈现它们。如果您创建一个List,如下所示:
List<Object> list = new ArrayList<>();
list.add(list);
System.out.println(list);toString()的简单实现会抛出StackOverflowError (尝试一下)。在某些情况下,Collection实现试图为一些核心方法抵抗这个问题;这就是这一段的意思。
https://stackoverflow.com/questions/45743814
复制相似问题