自引用集合引发堆栈溢出

时间:2015-12-30 10:58:45

标签: java generics collections

在学习自我参照收集的过程中,我想出了投掷的地方 堆栈溢出错误。

请在下面找到源代码。

import java.util.*;

public class TestSelfColl {

public static void main(final String[] args) {
    test(new ArrayList<Collection<?>>());
    test(new LinkedList<Collection<?>>());
    test(new HashSet<Collection<?>>());
    test(new LinkedHashSet<Collection<?>>());

}

private static void test(final Collection<Collection<?>> collection) {
    collection.add(collection);
    System.out.println(collection);
    try {
        System.out.println(collection.hashCode());
    } catch (final StackOverflowError err) {
        System.out.println(err + " for " + collection.getClass());
    }
  }

  }

真的想知道为什么会出现这个错误。

我的期望是我将输出为:

[(此收藏)]

123

...

但相反,我得到了......

[(此收藏)]

java.util.ArrayList类的java.lang.StackOverflowError

...

2 个答案:

答案 0 :(得分:1)

AbstractCollection不会发生这种情况,因为该类不会覆盖Object的{​​{1}}。

但是,如果您添加hashCode作为自身成员,ArrayList的{​​{1}}会遇到无限递归,因为ArrayList的{​​{1}} (在hashCode中实现)是其元素'hashCodes:

的函数
ArrayList

hashCode不会导致相同的无限递归的原因是此检查(在AbstractList中,public int hashCode() { int hashCode = 1; for (E e : this) hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); // e.hashCode() is a self call in your example return hashCode; } 未覆盖):

toString

答案 1 :(得分:0)

AbstractCollection.toString()有一个简单的检查来停止包含自己的集合的递归。

将相同的检查添加到AbstractSet.hashCode()和AbstractList.hashCode()将解决它