如何从外部块重新抛出一个lambda块中的异常? [英] How can I re-throw an exception in a lambda block as from the outer block?

查看:151
本文介绍了如何从外部块重新抛出一个lambda块中的异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用以下代码,

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? //  --/
        }
    });
}

如何抛出 sce 如果方法(供应商)方法抛出它?

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

请注意,上面的代码只是一个例。我需要键(s.get())在lambda表达式内。

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

void supplier(Supplier<Key> s) throws SomeCheckException {
    key(s.get());
}


推荐答案

异常以安全的方式需要一个帮助方法,该方法提供将异常包装到子类型 RuntimeException 中的功能。这是一个帮助函数,它使用Generic的类型安全性来确保只有声明的异常将被重新抛出(除非你使用不安全的操作):

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; }
}

它支持任意的动作它将接收一个函数,该函数将检查的异常类型临时包装到 RuntimeException 中。这个包装将是透明的,方法尝试将正常完成或抛出原始的检查异常 E (或一个无关的

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).

所以你可以这样使用:

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); }
        }));
}

由于嵌套操作,编译器无法自动推断异常类型。上面的代码使用 thrower 参数类型的明确声明。或者,您可以使用帮助器方法的类型调用,如

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); }
    }));

这篇关于如何从外部块重新抛出一个lambda块中的异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆