Skip to content
Francis Galiegue edited this page Apr 11, 2015 · 8 revisions

Interfaces...

For each functional interface Foo usable in Streams, this package defines an interface ThrowingFoo. For instance, here is the base code for 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 throwable) {
            throw new ThrownByLambdaException(throwable);
        }
    }
}

Note that it extends the base interface; any implementation (class, method reference, lambda...) is therefore also usable as the base type.

Throwing, and Chainer

The Chainer class is the basic abstract class which is implemented for all throwing functional interfaces; for an interface Foo:

  • the chainer implementation is called FooChainer,
  • it implements ThrowingFoo (therefore Foo as well).

A sample use would be:

// Return a ToLongFunctionChainer<Path>; return a default value if the function fails:
final ToLongFunction<Path> f = Throwing.toLongFunction(Files::size).orReturn(OL);

A Chainer implementation defines three methods:

  • orTryWith(): if the first throwing instance fails, try with another throwing instance; this returns a Chainer, therefore you can chain other instances from there;
  • orThrow(): throw an exception on failure; you'll have to specify an unchecked exception class which has a constructor accepting a single Throwable as an argument;
  • fallbackTo(): invoke a non throwing version of the functional interface on failure;
  • sneakyThrow(): uses the same trick as lombok's @SneakyThrows annotation to rethrow the exception thrown as is, even if checked.

In addition, implementations provide other methods depending on the type of the functional interface implemented. FunctionChain, for instance, provides .orReturn(); ConsumerChain provides .orDoNothing(); etc etc.

Implementing your own

You can implement your own version of a chainer for your own functional interfaces, or interfaces provided by the JDK which are not covered by this package. Recall that a Chainer implementation should implement the throwing version of the interface!

In addition, you can extend the Throwing class so as to add the matching method to invoke instances of your new Chainer implementation.

Clone this wiki locally