How can I re-throw an exception in a lambda block as from the outer block?

后端 未结 2 551
清酒与你
清酒与你 2021-01-05 18:04

With following code,

void key(Key) throws SomeCheckedException {
}

void supplier(Supplier s) throws Some         


        
相关标签:
2条回答
  • 2021-01-05 18:26

    If you want to process checked exceptions in a safe manner you need a helper method which provides the facility of wrapping the exception into a sub-type of RuntimeException. Here is such a helper function which uses Generic’s type safety to ensure that only declared exceptions will be re-thrown (unless you use 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 which will receive a function which does the temporary wrapping of the checked exception type to the RuntimeException. This wrapping will be transparent, the method attempt will either complete normally or throw the original checked exception E (or an unrelated unchecked exception if one occurs).

    So you can use it like this:

    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 the nested operations the compiler is unable to infer the exception type automatically. The code above use an explicit declaration of the thrower parameter type. Alternatively you can use a type invocation of the helper method like

    ContainingClass.<SomeCheckedException>attempt( thrower ->
        Optional.ofNullable(s).ifPresent(nonNull -> {
            try { key(nonNull.get()); }
            catch(SomeCheckedException  e) { throw thrower.apply(e); }
        }));
    
    0 讨论(0)
  • 2021-01-05 18:35

    You can't. Supplier#get() does not declare to throw any (checked) exceptions. Remember that a lambda expression simply creates an instance, it doesn't actually invoke the target functional interface method.

    If you want to, you can wrap the checked exception in an unchecked exception and throw that.

    0 讨论(0)
提交回复
热议问题