假设我有以下内容(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
的合同。
有没有办法让我解决这个问题,这样的解决办法会破坏其他任何东西吗?
答案 0 :(得分:0)
修改:让我试着更清楚一点:
这是Iterator类的正确用法:
x = 1..3
y = x.iterator();
while(y.hasNext()) {
println y.next();
}
NoSuchElement
异常是未经检查的(AKA运行时)异常。它没有被检查的原因是,它应该是完全可以避免的,而不依赖于异常。这与例如IOException
s不同,它们被检查并且在正常使用期间更有可能发生。
在文档中没有明确说明这种方式,但是我唯一一次看到next()
方法在上面正确使用迭代器时抛出NoSuchElementException
就是如果你有一个<在不同步的多线程环境中进行强>可修改集合,在您调用hasNext
并使用项目访问项目时,该项目已删除 next
。
因为Range
类是不可修改的,所以这种情况不可能出现。
您不应该依赖未经检查的例外来确定项目的功能或状态。
所以,我真的认为合同没有被打破。使用迭代器的合同是在hasNext
之前使用next
,并且Range类的Iterator不需要因为它被错误地使用而抛出异常。
答案 1 :(得分:0)
使用:
While(y.hasNext()){
println y.next();
}
答案 2 :(得分:0)
这是因为IntRangeIterator
在距离范围结束时返回null
As you can see in the source code for it here
我想如果您觉得这是不正确的行为,您应该在邮件列表上询问,或者将错误发布到Groovy JIRA,但是因为它是been that way for 6 years我会想象它会保持这种状态(如这将是一个突破性的变化)
正如其他人所说,您应该使用for
或each
机制来迭代Iterator
,或者如果不可能将您的来电包裹在next()
中{ {1}}检查应该捕获所有你不在的情况。