Java 8与Java7集合接口:自引用实例

时间:2017-08-17 19:46:19

标签: java-8 java-7

我正在阅读Java8集合界面文档。我注意到Java8 Collection Interface在说明中添加了此段落,但未包含在Java7 Collection Interface中。

  

执行递归遍历的一些集合操作   对于自引用实例,集合可能会失败   集合直接或间接包含自身。这个   包括clone(),equals(),hashCode()和toString()方法。   实现可以选择处理自引用场景,   但是大多数当前的实现都没有这样做。

我对此段落的原因感到有些困惑。是因为Java7不能拥有直接或间接包含自身集合的自引用实例吗?然后Java8引入了新的界面或一些允许的新功能?

我正在寻找详细解释,如果你举一个例子来说明你的观点,那将会很棒。谢谢!

2 个答案:

答案 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实现通常无法解决它,并且隐藏错误客户端的故障是有意义的必须避免使用代码,否则问题永远无法解决。

  

“实现可以选择处理自引用场景,   但是目前大多数实现都没有这样做。“