javaexceptioninterfacemapping

Adapt exception type of generic throwing iterator


I have an interface ThrowingIterator, which follows the general contract of Iterator, except the hasNext() and next() methods can throw exceptions:

public interface ThrowingIterator<T, E extends Throwable> {
  boolean hasNext() throws E;
  T next() throws E;
  default void remove() throws E { /* throw unsupported */ }
  // forEachRemaining same as Iterator
}

I can change the return type of the iterator by using an adapt function, similar to how Stream has map(Function<? super T, U> mapper). However, I haven't been able to figure out a way to change the exception type of the iterator, like the following:

// example method
default <X extends Throwable> ThrowingIterator<T, X> adaptException(Function<? super E, ? extends X> exceptionMapper) {
  return new ThrowingIterator<T, X> {
    public boolean hasNext() {
      try {
        return this.hasNext();
      } catch (E e) { // this does not work, can't catch E
        throw exceptionMapper.apply(e);
      }
    }
  }
  // same for next()
}

// example use
ThrowingIterator<Integer, IOException> baseIterator = getIterator();
ThrowingIterator<Integer, ExecutionException> adaptedIterator = baseIterator.adaptException(ExecutionException::new);

My main difficulty in writing this function comes from the fact that Java does not allow a generic exception type to be caught. Is there any way around this restriction? I could catch all Throwables and check if they're of the expected type using a class object, but that feels clunky.


Solution

  • I could catch all Throwables and check if they're of the expected type using a class object, but that feels clunky.

    I'm sorry it feels clunky to you, but it's your only option.