因此,出于好奇,我决定找出将列表添加到自身时会发生什么情况。由于列表只是一个对象,并且您可以在Java中拥有一个对象列表,所以我认为应该可以。
List<Object> a = new ArrayList<>();
a.add(a);
这确实可以编译并运行良好。所以我决定看看当我尝试打印它时会发生什么。
List<Object> a = new ArrayList<>();
a.add(a);
System.out.println(a);
这将输出:
[(this Collection)]
因此,显然Java开发人员想到了这种确切的情况,并添加了一个特殊情况来处理它。嗯,除了防止由于无限递归而导致崩溃(打印尝试打印包含a的a等)以外,它并不是特别有用(至少我看不到它的方便之处)。
除了这仅适用于一个列表:
List<Object> a = new ArrayList<>();
List<Object> b = new ArrayList<>();
a.add(b);
b.add(a);
System.out.println(a);
这将导致StackOverflow。因此很明显,这种处理方式不足以处理任意的引用循环-仅当您向自身添加列表时才起作用。那么,为什么要打扰呢?有什么意义?
PS:例如,Python似乎已对其进行了一般处理。
>>> l = []
>>> l += [l]
>>> l
[[...]]
>>> a = []
>>> b = []
>>> a += [b]
>>> b += [a]
>>> a
[[[...]]]
我读了[[[...]]]]
符号,因为a
是一个列表,其中包含一个列表,其中包含一个。
答案 0 :(得分:1)
(this Collection)
是在AbstractCollection#toString
中实现的,它会对其自身进行迭代并检查是否有任何成员是this
。 https://hg.openjdk.java.net/jdk/jdk/file/47ee6c00d27c/src/java.base/share/classes/java/util/AbstractCollection.java#l457
[...]
由repr
的{{1}}和其他人通过对listobject
的检查产生,该检查使用线程局部指令跟踪对象的重新进入:{{3} }
您可以尝试修补AbstractCollection实现,以使用线程本地字典-跟踪当前线程中当前正在toString的所有集合及其元素。它可能有效,也可能无效。可以猜测:Python解释器大体上是单线程的,这可能会使它更好地摆脱某些技巧,而遇到的Java问题可能只有通过并行修改才能明显地实现,否则这些修改是安全的。最好不要保证避免无法保证的无限递归。
答案 1 :(得分:-5)
实际上没有这样的东西叫做这个收藏集...
您可以从AbstractCollection.java
/**
* Returns a string representation of this collection. The string
* representation consists of a list of the collection's elements in the
* order they are returned by its iterator, enclosed in square brackets
* ({@code "[]"}). Adjacent elements are separated by the characters
* {@code ", "} (comma and space). Elements are converted to strings as
* by {@link String#valueOf(Object)}.
*
* @return a string representation of this collection
*/
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);
if (! it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
因此,这只是使此数组的toString对人类更易读的一种方法。
仅此而已。