-
Notifications
You must be signed in to change notification settings - Fork 8
How to use
Several things:
- a hand written lambda:
(list, of, arguments) -> { /* code of the lambda here }
; - a method reference (and there are a lot of possibilities; see here);
- an instance of a class implementing the expected functional interface;
- etc etc.
When you declare a ThrowingFoo
version of an interface Foo
as in:
final ThrowingFunction<Input, Output> function = someLambdaHere;
this variable is directly usable as a Foo
, since all ThrowingFoo
interfaces extend their Foo
counterparts.
The default behavior, which you can alter, is that if a checked exception is thrown, it is wrapped into a ThrownByLambdaException
.
You can, if you wish to, capture that exception and see the cause of the failure (using .getCause()
).
All unchecked exceptions (ie, RuntimeException
s) and Error
s are thrown as is.
For each functional interface covered by this package, there is an equivalent method in the Throwing
class which will return an instance of a Chainer
. For instance:
-
Throwing.function(...)
; -
Throwing.intConsumer(...)
; -
Throwing.longBinaryOperator(...)
; - etc etc.
You can customize the behavior of an interface in three ways:
- throw a different exception than the default:
.orThrow()
; - try with a different, throwable lambda:
.orTryWith()
; - fallback to a non throwable lambda of the same version:
.fallbackTo()
.
Note: .orTryWith()
is chainable, which means you can try with other throwing lambdas etc etc.
Examples:
Throwing.biFunction(my::method).orThrow(MyException.class);
Throwing.consumer(my -> { lambda(); here(); }).fallbackTo(nonThrowing -> { lambda(); here(); });
Throwing.intSupplier(first::lambda).orTrywith(other::lambda).fallbackTo(last::resort);
Throwing.doubleBinaryOperator(first::lambda).orTryWith(other::lambda).orThrow(MyException.class);
Depending on the type of throwing interface you have, you also have specific customizations available:
- all interfaces and their primitive versions except for
Consumer
s:.orReturn(someValue)
; -
Consumer
s:.orDoNothing()
; -
UnaryOperator
s:.orReturnSelf()
; -
BinaryOperator
s:.orReturnLeft()
,.orReturnRight()
.
Taking the example of Path::toRealPath
, here is how you would tell, in a stream, to return the argument itself if the method fails with an exception:
// Due to a limit in type inference, you have to declare this:
final FunctionChainer<Path, Path> chainer = Throwing.unaryOperator(Path::toRealPath);
// It is important to use Operators and not Functions here!
Files.list(someDir).map(chainer.orReturnSelf())