Groovy 为范围抛出NoTouchElementException

Groovy 为范围抛出NoTouchElementException,groovy,iterator,Groovy,Iterator,假设我有以下()项: 这将产生: 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,因此代码如下(): 现在我们得到了输出: 1 2 3 null 并且没有抛出

假设我有以下()项:

这将产生:

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
,因此代码如下():

现在我们得到了输出:

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


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

编辑::让我尽量说清楚:

这是迭代器类的正确用法:

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

while(y.hasNext()) {
    println y.next();
}
nosucheElement
异常是未经检查的(也称为运行时)异常。它没有被检查的原因是它是完全可以避免的,而不依赖于异常。这不同于,例如,
IOException
s,后者被检查,并且在正常使用过程中更可能发生

文档中没有明确说明这种或那种方式,但当迭代器如上所述正确使用时,我唯一一次看到
next()
方法抛出
NoSuchElementException
的情况是,如果在未同步的,多线程环境,在调用
hasNext
和使用
next
访问项目之间,删除了项目

因为
范围
类是不可修改的,所以这种情况永远不会出现

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

所以,我并不认为合同已经破裂。使用迭代器的约定是在
next
之前使用
hasNext
,并且不要求Range类的迭代器仅因为使用不正确而引发异常。

使用:

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

}

这是因为
IntRangeIterator
在超出范围结束时返回
null

我想如果你觉得这是不正确的行为,你应该在邮件列表上询问,或者在Groovy JIRA上发布一个bug,但事实上,我认为它将保持这种状态(因为这将是一个突破性的变化)


正如其他人所说,您应该使用
for
每一个
机制来迭代
迭代器
,或者如果这不可能,那么在
hasNext()中包装对
下一步()
的调用。
检查应该捕获所有您已经结束的情况。

此外,您没有任何实际示例。但是,由于您在groovy中,您可能应该使用
for(foo in range){println foo}
range.each{foo}
。过度热情:您引用的文本中没有任何声明抛出异常是可选的。也没有什么规定它是强制性的,但它是一个规范,如果默认情况下它是可选的,那么规范就是愚蠢的。我认为,
iterator
规范的语言意味着
hasNext()==false
IFF
next()抛出NoSuchElementException
。如果
FileNotFound
异常是可选的,您能想象Java会有多坏吗?这将迫使程序员在任何地方都进行
null
检查,然后猜测问题(因为
null
可能意味着任何东西)。Clinton,File类有一个称为exists(或isFile或isDirectory)的方便方法,因此您可以在使用该文件之前检查该文件是否存在。不需要检查null。同样,例外意味着出了问题。此外,与IOExceptions不同,NoTouchElement异常是未选中的。这是因为你不应该得到它。克林顿:我根据你的反馈改写了我的问题。我认为在这种情况下,澄清这是一个未经检查的异常,而不是所有异常更有意义。谢谢你的意见。
x = 1..3
y = x.iterator();

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

}