Java集合API存在漏洞?

3

我在Java集合API的Collections.java中发现了一个bug。

以下是来自JDK源代码的原始代码。请注意,JavaDoc版本标签为“1.106,04/21/06”。该方法位于第638行。

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
    Iterator<? extends T> i = coll.iterator();
    T candidate = i.next();

    while (i.hasNext()) {
        T next = i.next();
        if (next.compareTo(candidate) > 0)
            candidate = next;
    }
    return candidate;
}

如果您仔细分析这个方法,很快就会发现一个错误:T candidate = i.next()。天啊!在没有先检查hasNext()的情况下调用迭代器上的i.next()?这只是在寻求异常。
肯定应该在编码过程中注意到这样的问题吧?这意味着使用API必须检查集合是否至少有两个元素。

1
“这意味着使用API时必须检查集合中是否至少有两个元素。” - 实际上,这只是意味着您必须首先检查集合是否为空。只有在这种情况下,next()才会抛出异常。 - Michael Myers
3个回答

21

不可以。这意味着尝试从一个空集合中找到最大元素是无效的。这在API文档中有说明:

Throws:
    NoSuchElementException - if the collection is empty.

这就是文档中说明的 Iterator.next() 在没有下一个元素时会抛出的异常,因此它正好做了它应该做的事情。

请注意,在第一次调用 next() 后,需要调用 hasNext() 来检查是否有多个元素。


2
来吧,现在不是你该睡觉的时间了吗?我正要说同样的话呢。 - Michael Myers
对于只有一个元素的集合,正确的操作应该是返回该元素,而不是抛出异常。 - Humphrey Bogart
是的,我忽视了 while 块;我认为是其他原因导致了异常。 - Humphrey Bogart
@Steeve Reed,你不是这位来自英国雷丁市的32岁、已婚并育有三个孩子的谷歌员工和C#书籍作者的对手。 - Tom

7

很难称之为一个错误,因为异常在这里有记录。

抛出:

  • 如果集合包含不可相互比较的元素(例如字符串和整数),则会抛出ClassCastException。
  • 如果集合为空,则会抛出NoSuchElementException。

2
根据API文档Collection.max方法在集合为空时会抛出NoSuchElementException
这正是您所观察到的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接