With some frequency I find myself writing APIs that offer an Iterator<Foo> which is backed by a network connection. The implementation opens a network connection, reads information off the stream, and deserializes that information into Foos to pass on to the caller. Unfortunately there is always the possibility of an IOException and also the need to close the network connection gracefully (that can be made automatic when the caller reads the last Foo, but what if that doesn't happen?).
There are already a couple of questions (here and here) about how to deal with checked exceptions that would be thrown in an implementation of Iterator, and the accepted advice is "wrap them in unchecked RuntimeExceptions". Meanwhile to allow closing the network connection we can implement Closeable. So we end up with something like this for a well-behaved exception-checking caller:
Iterator<Foo> iter = null;
try {
iter = getFooIterator();
while(iter.hasNext()) {
Foo foo = iter.next();
// do something with foo
}
}
catch(RuntimeException e) {
if(e.getCause() instanceof IOException) {
// do something with the IOException
}
else throw e;
}
finally {
if(iter instanceof Closeable) try { ((Closeable)iter).close(); } catch(IOException e) {}
}
And it seemed like such a nice idea to implement Iterator. Is there a better way?
AutoCloseableand open the resources in the try statement, e.g.try(iter = getFooIterator();) { ... }(the iterator would have to implementAutoCloseablethough).next()orhasNext()) and then throw an exception. That way the user of the iterator would not have to worry about closing the iterator (and thus the underlying connection) and just would have to handle the exception.Iteratorthe caller can get to work on theFoos right away. That could make a significant difference if there are 1000s ofFoos coming over a slow network connection.