迭代器删除的Java异常契约
我正在实现一个,它使用另一个迭代器,我不知道它是否支持迭代器删除的Java异常契约,java,exception,collections,Java,Exception,Collections,我正在实现一个,它使用另一个迭代器,我不知道它是否支持remove()方法 考虑以下边缘情况:底层迭代器不支持remove(),对于我的迭代器next()尚未调用 如果我的remove()抛出一个IllegalStateException而不是UnsupportedOperationException,我是否违反了接口约定? (只要调用了next(),就可以调用底层的remove(),这将抛出相应的UnsupportedOperationException) 如果是这样,我如何重构代码以检查底层
remove()
方法
考虑以下边缘情况:底层迭代器不支持remove()
,对于我的迭代器next()
尚未调用
如果我的remove()
抛出一个IllegalStateException
而不是UnsupportedOperationException,我是否违反了接口约定?
(只要调用了next()
,就可以调用底层的remove()
,这将抛出相应的UnsupportedOperationException
)
如果是这样,我如何重构代码以检查底层迭代器是否支持remove()
例如:
<T> Iterator<T> getSetViewIterator(Collection<T> collection) {
Iterator<T> uniqueItr = new HashSet<>(collection).iterator();
return new Iterator<T>() {
private T current = null;
private boolean hasRemoved = true;
@Override
public boolean hasNext() {
return uniqueItr.hasNext();
}
@Override
public T next() {
if(!hasNext())
throw new NoSuchElementException();
hasRemoved = false;
return current = uniqueItr.next();
}
@Override
public void remove() {
if(hasRemoved)
throw new IllegalStateException();
for(Iterator<T> iterator = collection.iterator(); iterator.hasNext();) {
if(iterator.next().equals(current))
iterator.remove();
}
hasRemoved = true;
}
};
}
迭代器getSetViewIterator(集合){
迭代器uniqueItr=新哈希集(集合).Iterator();
返回新的迭代器(){
专用T电流=零;
私有布尔hasRemoved=true;
@凌驾
公共布尔hasNext(){
返回uniqueItr.hasNext();
}
@凌驾
公共交通工具{
如果(!hasNext())
抛出新的NoTouchElementException();
hasRemoved=false;
返回电流=uniqueItr.next();
}
@凌驾
公共空间删除(){
如果(已删除)
抛出新的非法状态异常();
for(Iterator Iterator=collection.Iterator();Iterator.hasNext();){
if(迭代器.next().equals(当前))
iterator.remove();
}
hasRemoved=true;
}
};
}
(出于我们的目的,我们可以假设传递的集合不包含null
)根据您链接到的文档,这两种异常都适用于remove
方法,并且明确提到了在next
之前调用remove
的情况,并允许抛出非法状态异常
对于不支持remove
的迭代器,始终抛出UnsupportedOperationException
与在非法状态下抛出IllegalStateException
一样有效(remove
在next
之前,第二个remove
在next
之后),并且只在有效状态下抛出另一个异常(第一次删除之后下一次)。这两种异常都适用于处于无效状态的调用,因为该状态无效且不支持该操作
您的包装迭代器工作正常-它检查无效状态,然后委托给内部迭代器,该迭代器可能会抛出其不受支持的操作异常。您的迭代器不需要知道内部迭代器是否支持删除,因为如上所述,在非法状态下,这两个异常都是有效的响应。根据您链接的文档,这两个异常对于删除方法都是可接受的,并且明确提到了在next
之前调用remove
的情况,并允许抛出IllegalStateException
对于不支持remove
的迭代器,始终抛出UnsupportedOperationException
与在非法状态下抛出IllegalStateException
一样有效(remove
在next
之前,第二个remove
在next
之后),并且只在有效状态下抛出另一个异常(第一次删除之后下一次)。这两种异常都适用于处于无效状态的调用,因为该状态无效且不支持该操作
您的包装迭代器工作正常-它检查无效状态,然后委托给内部迭代器,该迭代器可能会抛出其不受支持的操作异常。您的迭代器不需要知道内部迭代器是否支持remove,因为如上所述,在非法状态下,两个异常都是有效的响应。这两个异常都是在编写良好的应用程序中不应该出现的类型,因此我在实践中看不到有太多问题。诚然,但作为一个完美主义者,它确实让我感到厌烦,remove()
更改其异常。我认为,如果底层迭代器不支持它,它应该总是抛出一个UnsupportedOperationException
,我只是不知道如何实现这一点……在这种情况下,我想说,你应该记住你是否已经抛出了一个ISE,并在对象的剩余生命周期中一直抛出它。我知道这不是你想要的,但它是一致的。这反过来肯定会违反合同,因为在(成功的)next
之后,没有理由抛出IllegalStateException
。你可以随时抛出IllegalStateException
,你可以定义自己的合同。一旦你进入非法状态,就没有义务仅仅因为有人调用了next()
就退出它。物理上不可能的一件事是,即使在第一个next()
之前,底层迭代器总是抛出UOE。这两种异常都是在编写良好的应用程序中永远不会发生的,因此我在实践中看不到有太多的问题。诚然,作为一个完美主义者,这确实让我很恼火,remove()
更改其异常。我认为,如果底层迭代器不支持它,它应该总是抛出一个UnsupportedOperationException
,我只是不知道如何实现这一点……在这种情况下,我想说,你应该记住你是否已经抛出了一个ISE,并在对象的剩余生命周期中一直抛出它。我知道这不是你想要的,但这是一贯的。这反过来肯定会违反合同,不是吗