Ant*_*nio 8 java iterator ioexception java-7
我想实现一个从磁盘/网络中检索对象的迭代器.
Iterator itr = getRemoteIterator();
while(itr.hasNext()) {
Object element = itr.next();
System.out.print(element + " ");
}
Run Code Online (Sandbox Code Playgroud)
然而问题是,hasNext()
和next()
该方法的迭代器对象不允许扔IOException
.是否还有其他标准接口可以解决此问题?
期望的代码是:
public interface RemoteIterator<E> {
boolean hasNext() throws IOException;
E next() throws IOException;
void remove();
}
Run Code Online (Sandbox Code Playgroud)
不幸的是你不能这样做.声明的异常是方法签名的一部分,而你可以缩小范围,例如
interface FooCallable extends Callable<T> {
T call() throws IOException; // Narrows Exception from the parent interface
}
Run Code Online (Sandbox Code Playgroud)
你不能引入新的throws子句或扩大声明的子句.
Iterator
是一个基本的Java接口,由增强版使用,所以即使你能以某种方式做你想做的事情,编译器也需要知道
for (T obj: ioExceptionThrowingIterable) { ... }
Run Code Online (Sandbox Code Playgroud)
要求检查IOException
被抓住或抛出.
这是意见问题,但我认为您应该使用自定义子类RuntimeException
并仔细记录您的界面.在现代框架中避免了检查异常,例如Spring,因为它们存在相关问题.
编辑:借用并改编自user949300的答案,您可以将返回的对象包装在例如
interface RemoteObject<T> {
T get() throws IOException
}
Run Code Online (Sandbox Code Playgroud)
然后返回一个Iterator<RemoteObject<T>>
,并强制调用者处理打开IOException
时get
:
for (RemoteObject<Foo> obj: iterable) {
try {
foo = obj.get()
} catch (IOException ex) {
/*
* 9 times out of 10, the lazy user just prints the stack trace
* or something else inappropriate
* which is why I despise checked exceptions
*/
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,没有必要扩展Iterator
,它可以直接使用.事实上,Collection
如果适用,您可以使用.
这不完全是你想要的,但考虑:
这是通过网络发生的,因此可能很慢.你可能应该使用Future
(或类似的).
所以,不要让你的RemoteIterator<E>
位置next()
返回E,而是使用
RemoteIterator<Future<E>>
,它返回一个Future<E>
.
在该Future.get()
方法中,您可以将任何内容包装IOException
在中ExecutionException
.
不完美,但Future.get()
暗示事情可能会很慢,而且它会抛出一个检查异常,这将使其他程序员发现正在发生的事情,并且自然的响应是调用getCause()
.因此,这避免了大多数"WTF"方面.