Как известно из функциональных интерфейсов в Stream API нельзя выбрасывать контролируемые исключения. Если по каким-то причинам это необходимо (например, работа с файлами, базами данных или по сети), приходится оборачивать их в RuntimeException. Это неплохо работает если ошибки игнорируются, но если их необходимо обрабатывать, то код получается громоздкий и трудночитаемый. Я заинтересовался можно ли объявлять интерфейсы и методы с generic исключениями и неожиданно для себя узнал, что можно.
Зададим такой функциональный интерфейс, от стандартного интерфейса Function<A, B> он отличается только наличием третьего generic-типа для бросаемого исключения.
public interface ThrowableFunction<A, B, T extends Throwable>{
B apply(A a) throws T;
}
И объявим простенький метод, который преобразует коллекцию используя этот интерфейс, у этого метода также объявлен generic-тип для бросаемого исключения (совпадающий с типом исключения которое может выбросить функциональный интерфейс).
public static <A, B, T extends Throwable> Collection<B> map(Collection<A> source, ThrowableFunction<A, B, T> function) throws T {
Collection<B> result = new ArrayList<>();
for (A a : source) {
result.add(function.apply(a));
}
return result;
}
Посмотрим, как будет выглядит обработка исключений с ними в разных случаях.
Читать полностью »