Как вернуть первое возникшее исключение?
Есть метод validate, который в качестве входных данных принимает экземпляр Option
и Predicate
- два аргумента (да, я знаю Option
должны быть переданы в качестве аргумента, но это упрощенный сценарий реального мира здесь. Сейчас если Option
пусто мне нужно бросить NotFoundException
, Когда оно имеет значение, которое не соответствует Predicate
прошло это должно потерпеть неудачу с ForbiddenException
, Если оно имеет значение и соответствует предикату, ничего не происходит.
Так что это будет:
Option, Predicate
/\
isEmpty() / \ isDefined()
/ \
throw NFE matches(Predicate)
/ \
no / \ yes
/ \
throw FE end
У меня есть некоторые решения, но я хотел бы, чтобы потенциальные ответчики пришли к этому вопросу с ясным умом;) Моя проблема - получить первое исключение, если оба теста не пройдены. Я ожидаю элегантного решения, если я могу ожидать чего-либо;) Все существа вавр позволили (Either
, Validation
, Try
..)
Одна из идей заключается в использовании двойного Option
:
Option
.of(o.getOrElseThrow(NotFoundException::new))
.filter(p)
.getOrElseThrow(ForbiddenException::new);
Но это кажется немного неловким.
Здесь образец проекта можно найти.
3 ответа
На мой взгляд, лучшим вариантом было бы создать читаемый код, что в данном случае означает использование двух if
заявления:
if (!o.isPresent()) throw new NotFoundException();
if (!p.test(o.get())) throw new ForbiddenException();
Простой, читаемый и понятный для тех, кому понадобится сохранить этот код в будущем.
Если, тем не менее, вы хотите сделать это в каком-то функциональном стиле:
o.orElseThrow(NotFoundException::new);
o.filter(p).orElseThrow(ForbiddenException::new);
С Java 9:
o.ifPresentOrElse(
t -> if (!p.test(t)) throw new ForbiddenException(),
() -> throw new NotFoundException());
Это было бы решением с Optional
(нет времени проверять vavr
но должно быть достаточно близко)
public static <T> void validate( Optional<T> optional, Predicate<T> pred ) throws NotFoundException, ForbiddenException {
if ( !pred.test( optional.orElseThrow( NotFoundException::new ) ) )
throw new ForbiddenException();
}
Не знаю, какой красивый способ бросить это ForbiddenException
к несчастью.
Если вы хотите полнофункциональное решение, вам понадобится Optional
Optional.of(
pred.test(
option.orElseThrow( NotFoundException::new )
)
).filter( b -> b ).orElseThrow( ForbiddenException::new );
Исключение выдается в правильном порядке, так как мы проверяем только Predicate
после option
проверять.
final CheckedFunction2<Option<T>, Predicate<T>, T>
f = (option, predicate) ->
Try.of(() -> option.getOrElseThrow(NotFoundException::new))
.filter(predicate, ForbiddenException::new)
.get();