【问题标题】:Self Referential Collections throws stack overflow自引用集合引发堆栈溢出
【发布时间】:2015-12-30 10:58:44
【问题描述】:

在学习自我参照集合时,我想出了它在哪里扔 堆栈溢出错误。

请在下面找到源代码。

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

...

【问题讨论】:

标签: java generics collections


【解决方案1】:

AbstractCollection 不会发生这种情况,因为该类不会覆盖 ObjecthashCode

但是,如果您将 ArrayList 添加为其自身的成员,则 ArrayListhashCode 会陷入无限递归,因为 ArrayListhashCode(在 AbstractList 中实现)是其元素的hashCodes函数:

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 不会导致相同的无限递归的原因是这个检查(在AbstractCollection 中,未被ArrayList 覆盖):

public String toString() {
    Iterator<E> it = iterator();
    if (! it.hasNext())
        return "[]";

    StringBuilder sb = new StringBuilder();
    sb.append('[');
    for (;;) {
        E e = it.next();
        sb.append(e == this ? "(this Collection)" : e); // here self calls are prevented
        if (! it.hasNext())
            return sb.append(']').toString();
        sb.append(',').append(' ');
    }
}

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2022-11-11
      • 1970-01-01
      • 1970-01-01
      • 2011-05-06
      • 1970-01-01
      • 2019-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多