Yes, they are:
@FunctionalInterface
public interface ThrowingConsumer<T, E extends Throwable> {
void accept(T value) throws E;
}
public static <T, E extends Throwable> void forEach(Collection<T> elements, ThrowingConsumer<T, E> consumer) throws E {
for (T element : elements) {
consumer.accept(element);
}
}
There is a significant shortcoming, which is that you can't catch exceptions using the type parameter - this does not compile: public static <T, E extends Throwable> Optional<E> forEach(Collection<T> elements, ThrowingConsumer<T, E> consumer) {
for (T element : elements) {
try {
consumer.accept(element);
} catch (E e) { // <-- not allowed!
return Optional.of(e);
}
}
return Optional.empty();
}
You can kludge your way around that in various ways, but none of them are pretty.