views:

226

answers:

6

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);
        }
    }

    ...
}
A: 

If your implementation doesn't have the properties required by the Iterator interface, why do you want to use it?

I see no other solution than the RuntimeException (with it's issues).

Marcel J.
+1  A: 

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.

helios
Another option, if you can't control UI client code: create an iterator that register the exceptions somewhere accesible by a getter or something, or call a callback interface, or something you control and can display the error anywhere. If that is useful to you, you can create a "CatcherIterator" that simply wraps a runtime-exception-thrower-iterator and catchs all posible exceptions redirecting them to the property or callback interface.
helios
+4  A: 

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:

  1. "Does Java need Checked Exceptions?" by Bruce Eckel
  2. The Trouble with Checked Exceptions A Conversation with Anders Hejlsberg, by Bill Venners with Bruce Eckel
  3. Java Design Flaws, C2 wiki

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.

Rorick
+1  A: 

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.

Stephen C
A: 

hasNext should not really throw an exception - it should check that it is ok to proceed and return a boolean value on that basis (I would log any underlying exceptions with a logger). I would throw a RuntimeException if next fails (and log the checked exception with a logger). Next should not fail in normal conditions if the test was ok and if the test fails you should not call next (hence runtime exception).

A: 

Whatever you do, do not use this trick :-)

http://blog.quenta.org/2006/11/generic-exceptions.html

finnw