-
Notifications
You must be signed in to change notification settings - Fork 8
How it works
fge edited this page Dec 27, 2014
·
8 revisions
Credits where they are due: thanks to Vincentyfication for the design idea
For each functional interface Foo
usable in Stream
s, this package defines an interface
ThrowingFoo
. For instance, here is the interface ThrowingFunction
:
@FunctionalInterface
public interface ThrowingFunction<T, R>
extends Function<T, R>
{
R doApply(T t)
throws Throwable;
@Override
default R apply(T t)
{
try {
return doApply(t);
} catch (Error | RuntimeException e) {
throw e;
} catch (Throwable tooBad) {
throw new ThrownByLambdaException(tooBad);
}
}
default Function<T, R> orReturn(R defaultValue)
{
return t -> {
try {
return doApply(t);
} catch (Error | RuntimeException e) {
throw e;
} catch (Throwable ignored) {
return defaultValue;
}
};
}
default <E extends RuntimeException> Function<T, R> orThrow(
Class<E> exceptionClass)
{
return t -> {
try {
return doApply(t);
} catch (Error | RuntimeException e) {
throw e;
} catch (Throwable tooBad) {
throw ThrowablesFactory.INSTANCE.get(exceptionClass, tooBad);
}
};
}
}
As you can see, all RuntimeException
s and Error
s are left untouched. Any other Throwable
depends on what you use :
- by default, they are wrapped into an unchecked
ThrownByLambdaException
, and the cause is set as thisThrowable
; - if you chain with
.orThrow(SomeException.class)
then this exception (which must also be unchecked) is thrown instead, and the cause is also set as theThrowable
thrown by the lambda; - if you chain with
.orReturn(someValue)
then this value is returned instead.
All functional interfaces extended this way have .orThrow()
; as to other chaining methods, they depend on the return types of their interface (Consumer
s have .orDoNothing()
for instance, and Operator
s have .orReturnSelf()
in addition to .orReturn()
).
The wrapper methods are defined in a utility class and simply wraps a ThrowingFoo
into a Foo
. For
Function
, this is defined in class Functions
:
// Old
public static <T, R> Function<T, R> rethrow(final ThrowingFunction<T, R> f)
{
return f;
}
// New
public static <T, R> ThrowingFunction<T, R> wrap(final ThrowingFunction<T, R> f)
{
return f;
}