2

可以说我有以下(ideone):

x = [1,2,3]
y = x.iterator();

println y.next();
println y.next();
println y.next();
println y.next();

这输出:

1
2
3
Caught: java.util.NoSuchElementException
java.util.NoSuchElementException
    at java_util_Iterator$next.call(Unknown Source)
    at prog.run(prog.groovy:7)

正如预期的那样。

但是让我们更改x = [1,2,3]x = 1..3,因此代码如下(ideone):

x = 1..3
y = x.iterator();

println y.next();
println y.next();
println y.next();
println y.next();

现在我们得到输出:

1
2
3
null

并且没有抛出异常。为什么会这样?[1,2,3] 和 1..3 在迭代它们时表现不同,这真是出乎意料。这样的行为似乎不符合iterator' 的合同。

我有没有办法解决这种行为,这样的修复会破坏其他任何东西吗?

4

3 回答 3

1

编辑:让我尝试更清楚:

这是 Iterator 类的正确用法:

x = 1..3
y = x.iterator();

while(y.hasNext()) {
    println y.next();
}

NoSuchElement异常是未经检查的(AKA 运行时)异常。不检查它的原因是它应该是完全可以避免的,而不依赖于异常。这与例如IOExceptions 不同,后者在正常使用期间被检查并且更有可能发生。

它没有在文档中明确说明一种或另一种方式,但是我唯一一次看到在正确使用迭代器时next()抛出 a 的方法NoSuchElementException是,如果您在具有项目的非同步多线程环境中有一个可修改的集合在您调用和使用 访问项目之间删除hasNextnext

因为Range类是不可修改的,所以这种情况永远不会上升。

您不应依赖未经检查的异常来确定项目的功能或状态。

所以,我真的不认为合同已经被破坏了。使用迭代器的约定是使用hasNextbefore next,并且 Range 类的 Iterator 不需要因为使用不正确而抛出异常。

于 2013-07-09T04:57:36.150 回答
0

这是因为当它超出范围的末端时IntRangeIterator返回null

正如您在此处的源代码中看到的那样

我想如果你觉得这是不正确的行为,你应该在邮件列表中询问,或者向 Groovy JIRA 发布一个错误,但由于6 年来一直这样,我想它会保持这种状态(因为它会是一个突破性的变化)

正如其他人所说,您应该使用fororeach机制来迭代Iterator,或者如果不可能将您的调用包装next()hasNext()检查中,则应该捕获所有您未完成的情况。

于 2013-07-09T07:55:31.113 回答
0

利用 :

While(y.hasNext()){
 println y.next();

}
于 2013-07-09T06:14:53.857 回答