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

The toString() format for List is specified; it must recursively toString() the contents and render them in a comma-separated list delimited by [ ... ]. If you create a List as follows:

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

a naive implementation of toString() would throw StackOverflowError (try it.) The Collection implementations try to defend against this problem for some core methods, in some cases; that's what this paragraph is saying.


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?

I don't think so.
Before Java 8, instances may of course have self reference.
And using them in a Collection may create of course infinite loops and failure at runtime with a StackOverflowError thrown.

Here two classes where instance fields have circular dependencies between them and which the toString() method of each class relies on their own fields.

Parent that refers to Child :

public class Parent {
    private List<Child> childs;

    public Parent(List<Child> childs) {
       this.childs = childs;
    }   

    @Override
    public String toString() {
      return "Parent [childs=" + childs + "]";
    }

}

Child that refers to Parent :

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 + "]";
    }

}

Suppose now you create a Child and a associated Parent :

List<Child> childs = new ArrayList<>();
Child child = new Child();
childs.add(child);

Parent parent = new Parent(childs);
child.setParent(parent);

Now you can invoke :

parent.toString();
child.toString();

or on a Collection instance such as :

childs.toString();

You will get exactly the same result : java.lang.StackOverflowError

as the child invokes the parent that invokes the child that invokes the parent and so on...

The doc was very probably updated with Java 8 to enforce the risk of implementing these methods in a brittle way as the Collection implementations generally don't address it and it makes sense as hiding the malfunctioning of a bugged client code has to be avoided otherwise the problem will never be solved.

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

Tags:

Java 7

Java 8