How can I throw an exception in a lambda block as from an external block?

With the following code

void key(Key) throws SomeCheckedException { } void supplier(Supplier<Key> s) throws SomeCheckedException { ofNullable(s).ifPresent(s -> { // | try { // | key(s.get()); // | } catch (final SomeCheckedException sce) { // | // sce is coming from key() method // | // How can I throw sce for outer method? // --/ } }); } 

How can I throw sce as if the method of the method ( supplier ) is throwing it?

Please note that the above code is just an example. I need key(s.get()) be inside the lambda expression.

 void supplier(Supplier<Key> s) throws SomeCheckException { key(s.get()); } 
+6
java lambda java-8 exception-handling
source share
2 answers

If you want to handle checked exceptions in a safe manner, you need a helper method that provides the ability to wrap the exception in a subtype of RuntimeException . Here is a helper function that uses Generics type security to ensure that only declared exceptions are thrown back (unless you are using an unsafe operation):

 public static <E extends Throwable> void attempt( Consumer<Function<E,RuntimeException>> action) throws E { final class CarryException extends RuntimeException { final E carried; CarryException(E cause) { super(cause); carried=cause; } } try { action.accept( CarryException::new ); } catch(CarryException ex) { throw ex.carried; } } 

It supports an arbitrary action that will receive a function that temporarily packs the checked exception type in a RuntimeException . This package will be transparent, the attempt method will either end normally or throw the original exception E (or an unbound exception if it occurred).

So you can use it as follows:

 public static void processIterm(Supplier<Key> s) throws SomeCheckedException { attempt( (Function<SomeCheckedException, RuntimeException> thrower) -> Optional.ofNullable(s).ifPresent(nonNull -> { try { key(nonNull.get()); } // assuming key may throw SomeCheckedException catch(SomeCheckedException e) { throw thrower.apply(e); } })); } 

Due to nested operations, the compiler cannot automatically infer the type of exception. The code above uses an explicit declaration of the thrower parameter type. Alternatively, you can use a call like helper method, e.g.

 ContainingClass.<SomeCheckedException>attempt( thrower -> Optional.ofNullable(s).ifPresent(nonNull -> { try { key(nonNull.get()); } catch(SomeCheckedException e) { throw thrower.apply(e); } })); 
+2
source share

You can not. Supplier#get() does not declare rejected (marked) exceptions. Remember that the lambda expression simply creates an instance; it does not actually call the target functional interface method.

If you want, you can wrap the thrown exception in the exception and throw it.

+7
source share

All Articles