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 Throwable
s and check if they're of the expected type using a class object, but that feels clunky.
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.