我正在阅读Java8集合界面文档。我注意到Java8 Collection Interface在说明中添加了此段落,但未包含在Java7 Collection Interface中。
执行递归遍历的一些集合操作 对于自引用实例,集合可能会失败 集合直接或间接包含自身。这个 包括clone(),equals(),hashCode()和toString()方法。 实现可以选择处理自引用场景, 但是大多数当前的实现都没有这样做。
我对此段落的原因感到有些困惑。是因为Java7不能拥有直接或间接包含自身集合的自引用实例吗?然后Java8引入了新的界面或一些允许的新功能?
我正在寻找详细解释,如果你举一个例子来说明你的观点,那将会很棒。谢谢!
答案 0 :(得分:6)
指定了toString()
的{{1}}格式;它必须递归List
内容并将它们呈现在由toString()
分隔的逗号分隔列表中。如果您按如下方式创建[ ... ]
:
List
List<Object> list = new ArrayList<>();
list.add(list);
System.out.println(list);
的简单实现会抛出toString()
(尝试它。)StackOverflowError
实现尝试在某些情况下针对某些核心方法来防范此问题;这是本段所说的内容。
答案 1 :(得分:5)
是不是因为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和一个关联的Parent:
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
实现通常无法解决它,并且隐藏错误客户端的故障是有意义的必须避免使用代码,否则问题永远无法解决。
“实现可以选择处理自引用场景, 但是目前大多数实现都没有这样做。“