Java 8 vs Java 7 集合接口:自引用实例

Java 8 vs Java 7 Collection Interface: self-referential instance

我正在阅读Java 8 集合接口文档。我注意到 Java 8 Collection Interface added this paragraph in the description which is not included in Java 7 Collection Interface .

Some collection operations which perform recursive traversal of the collection may fail with an exception for self-referential instances where the collection directly or indirectly contains itself. This includes the clone(), equals(), hashCode() and toString() methods. Implementations may optionally handle the self-referential scenario, however most current implementations do not do so.

我有点不明白为什么要包括这一段。是因为 Java7 不能有集合直接或间接包含自身的自引用实例吗?然后Java 8引入了新的界面或一些允许的新功能?

我正在寻找详细的解释,如果你能提供一个例子来说明你的观点,那就太好了。

指定了ListtoString()格式;它必须递归 toString() 内容并将它们呈现在由 [ ... ] 分隔的逗号分隔列表中。如果你创建一个 List 如下:

List<Object> list = new ArrayList<>();
list.add(list);
System.out.println(list);

toString() 的天真实现会抛出 WhosebugError(试试吧。)在某些情况下,Collection 实现试图为一些核心方法抵御这个问题;这就是这一段所说的。

Is it because Java7 cannot have self-referential instances where collection directly or indirectly contains itself? Then Java8 introduced new interface or some new feature that allows that?

我不这么认为。
在 Java8 之前,实例当然可以有自引用。
Collection 中使用它们当然可能会在运行时创建无限循环和失败并抛出 WhosebugError

这里有两个 classes,其中实例字段之间存在循环依赖关系,每个 class 的 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 + "]";
    }

}

假设您现在创建一个子对象和一个关联的父对象:

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.WhosebugError

当子调用父调用父调用子调用父等等...

该文档很可能更新为 Java 8 以加强以脆弱的方式实施这些方法的风险,因为 Collection 实施通常不解决它并且隐藏是有意义的必须避免错误的客户端代码的故障,否则问题将永远无法解决。

"Implementations may optionally handle the self-referential scenario, however most current implementations do not do so."