The java.lang.Iterator
interface has 3 methods: hasNext
, next
and remove
. In order to implement a read-only iterator, you have to provide an implementation for 2 of those: hasNext
and next
.
My problem is that these methods does not declare any exceptions. So if my code inside the iteration process declares exceptions, I must enclose my iteration code inside a try/catch block.
My current policy has been to rethrow the exception enclosed in a RuntimeException
. But this has issues because the checked exceptions are lost and the client code no longer can catch those exceptions explicitly.
How can I work around this limitation in the Iterator class?
Here is a sample code for clarity:
class MyIterator implements Iterator
{
@Override
public boolean hasNext()
{
try
{
return implementation.testForNext();
}
catch ( SomethingBadException e )
{
throw new RuntimeException(e);
}
}
@Override
public boolean next()
{
try
{
return implementation.getNext();
}
catch ( SomethingBadException e )
{
throw new RuntimeException(e);
}
}
...
}
You should rethrow exception as custom runtime exception, not generic one, for instance SomethingBadRuntimeException
. Also, you can try exception tunneling.
And I'm assured that forcing client to deal with exceptions by making them checked is a bad practice. It just pollutes your code or forces to wrap exceptions with runtime ones or force to process them in place of call but not centralized. My policy is to avoid using checked exceptions as much as possible. Consider IOException
on Closable.close()
: is it useful or convenient? Cases when it is are very rare, but every Java developer in the world is forced to deal with it. Most often it is swallowed or logged at best. And imagine how much this adds to code size!
There's some posts about checked exceptions from their dark side:
There are cases when checked exceptions comes to rescue. But in my opinion they are rare and usually concern to implementation of some specific module. And they don't give very much profit.
I've implemented a lot of Iterator, sometimes on top of with-check-exception iterators (ResultSet is conceptually a record iterator, InputStream y conceptually a byte iterator) and so on. It's very very nice and handy (you can implement pipe & filters architecture for a LOT of things).
If you prefer to declare your exceptions, then declare a new type of Iterator (ExceptionIterator, it would be like Runnable and Callable). You can use it along or your code but you can't compose it with outside components (Java Class Library or 3d party libs).
But if you prefer to use super-standard interfaces (like iterator) to use them anywhere, then use Iterator. If you know your Exceptions will be a condition for stop your processing, or you don't mind a lot... use them.
Runtime exceptions are not so terrible. By example. Hibernate use them to implement proxies and stuff like that. They have to except DB exceptions but can't declare them in their implementations of List.
As someone who likes Java checked exceptions, I think that the problem (Java design flaw if you will) is that the standard libraries don't support a generic Iterator type where the next
method throws a checked exception.
The code base for Sesame has an Iterator variant class called Iterable that does just that. The signature is as follows:
Interface Iteration<E,X extends Exception> Type Parameters: E - Object type of objects contained in the iteration. X - Exception type that is thrown when a problem occurs during iteration.
This seems to work in the limited context of Sesame, where specific subclasses are used that "fix" the exception type parameter. But (of course) it doesn't integrate with the standard collection types, Java 5's new for
loop syntax, and so on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With