[英]How can I re-throw an exception in a lambda block as from the outer block?
使用以下代碼,
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
仿佛方法( supplier
)方法把它扔?
請注意,上面的代碼只是一個例子。 我需要key(s.get())
在lambda表達式中。
void supplier(Supplier<Key> s) throws SomeCheckException {
key(s.get());
}
你不能。 Supplier#get()
不會聲明拋出任何(已檢查)異常。 請記住,lambda表達式只是創建一個實例,它實際上並不調用目標功能接口方法。
如果您願意,可以將已檢查的異常包裝在未經檢查的異常中並拋出該異常。
如果要以安全的方式處理已檢查的異常,則需要一個輔助方法,該方法提供將異常包裝到RuntimeException
子類型中的功能。 這是一個輔助函數,它使用Generic的類型安全性來確保只重新拋出聲明的異常(除非你使用不安全的操作):
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; }
}
它支持一個任意action
,它將接收一個函數,該函數將已檢查的異常類型臨時包裝到RuntimeException
。 此包裝將是透明的,方法attempt
將正常完成或拋出原始的已檢查異常E
(或者如果出現一個不相關的未經檢查的異常)。
所以你可以像這樣使用它:
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
參數類型的顯式聲明。 或者,您可以使用輔助方法的類型調用
ContainingClass.<SomeCheckedException>attempt( thrower ->
Optional.ofNullable(s).ifPresent(nonNull -> {
try { key(nonNull.get()); }
catch(SomeCheckedException e) { throw thrower.apply(e); }
}));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.