Исключения в лямбда-выражении с использованием Vavr

Исключения в лямбда-выражении с использованием Vavr

1. Вступление

Functional Interfaces, предоставленные JDK, не подготовлены должным образом для обработки проверенных исключений. Если вы хотите узнать больше о проблеме, отметьтеthis article.

В этой статье мы рассмотрим различные способы решения таких проблем с помощью функциональной библиотеки JavaVavr.

Чтобы получить дополнительную информацию о Vavr и о том, как его настроить, посетитеthis article.

2. ИспользуяCheckedFunction

Vavr предоставляетfunctional Interfaces с функциями, которые генерируют проверенные исключения. Это функцииCheckedFunction0,CheckedFunction1 и так далее доCheckedFunction8. 0, 1, … 8 в конце имени функции указывает количество входных аргументов для функции.

Давайте посмотрим на пример:

static Integer readFromFile(Integer integer) throws IOException {
    // logic to read from file which throws IOException
}

Мы можем использовать вышеуказанный метод внутри лямбда-выражения без обработкиIOException:

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);

CheckedFunction1 readFunction = i -> readFromFile(i);
integers.stream()
 .map(readFunction.unchecked());

Как видите, без стандартныхtry-catch или методов оболочки мы все еще можем вызывать методы генерации исключений внутри лямбда-выражения.

Мы должны проявлять осторожность при использовании этой функции с APIStream, так как исключение немедленно прервет операцию - оставив остальную часть потока.

3. Использование вспомогательных методов

Класс API предоставляет метод ярлыка для примера из предыдущего раздела:

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);

integers.stream()
  .map(API.unchecked(i -> readFromFile(i)));

4. Использование подъема

Чтобы изящно обрабатыватьIOException, мы можем ввести стандартные блокиtry-catch внутри лямбда-выражения. Однако краткость лямбда-выражения будет потеряна. На помощь нам приходит подъемник Вавра.

Лифтинг - это понятие из функционального программирования. Вы можете поднять частичную функцию до полной функции, которая возвращаетOption в качестве результата.

Частичная функция - это функция, которая определена только для подмножества домена, в отличие от полной функции, которая определена для всей ее области. Если частичная функция вызывается с вводом, выходящим за пределы его диапазона поддержки, она обычно выдает исключение.

Давайте перепишем пример из предыдущего раздела:

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);

integers.stream()
  .map(CheckedFunction1.lift(i -> readFromFile(i)))
  .map(k -> k.getOrElse(-1));

Обратите внимание, что результатом поднятой функции будетOption, а в случае исключения результатом будетOption.None. МетодgetOrElse() принимает альтернативное значение для возврата в случаеOption.None.

5. ИспользуяTry

Хотя методlift() из предыдущего раздела решает проблему внезапного завершения программы, он фактически проглатывает исключение. Следовательно, потребитель нашего метода не имеет представления о том, что привело к значению по умолчанию. Альтернативой является использование контейнераTry.

Try - это специальный контейнер, в который мы можем заключить операцию, которая может вызвать исключение. В этом случае результирующий объектTry представляет собойFailure и обертывает исключение.

Давайте посмотрим на код, который используетTry:

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);
integers.stream()
  .map(CheckedFunction1.liftTry(i -> readFromFile(i)))
  .flatMap(Value::toJavaStream)
  .forEach(i -> processValidValue(i));

Чтобы узнать больше о контейнереTry и о том, как его использовать, проверьтеthis article.

6. Заключение

В этой быстрой статье мы показали, как использовать возможности библиотеки Vavr для обхода проблем при работе с исключениями в лямбда-выражениях.

Хотя эти функции позволяют нам элегантно работать с исключениями, их следует использовать с максимальной осторожностью. С некоторыми из этих подходов потребители ваших методов могут быть удивлены неожиданными проверенными исключениями, хотя они явно не объявлены.

Полный исходный код для всех примеров в этой статье можно найти наover on Github.