小編典典
你必須先捕獲異常,然後才能轉出lambda:
s = s.filter(a -> { try { return a.isActive(); }
catch (IOException e) { throw new UncheckedIOException(e); }}});
考慮以下事實:在JDK類中,lambda不在你編寫的位置評估,而是在某些完全不相關的位置評估。這樣便可以抛出該檢查異常,并且在該位置不聲明該異常。
你可以通過使用lambda的包裝來處理它,該包裝将已檢查的異常轉換為未檢查的異常:
public static T uncheckCall(Callable callable) {
try { return callable.call(); }
catch (RuntimeException e) { throw e; }
catch (Exception e) { throw new RuntimeException(e); }
}
你的示例将寫為
return s.filter(a -> uncheckCall(a::isActive))
.map(Account::getNumber)
.collect(toSet());
在我的項目中,我無需包裝即可處理此問題;取而代之的是,我使用一種有效地緩解編譯器對異常檢查的方法。不用說,應該小心處理,項目中的每個人都必須意識到,未經聲明的異常可能會出現在經過檢查的異常中。這是管道代碼:
public static T uncheckCall(Callable callable) {
try { return callable.call(); }
catch (Exception e) { return sneakyThrow(e); }
}
public static void uncheckRun(RunnableExc r) {
try { r.run(); } catch (Exception e) { sneakyThrow(e); }
}
public interface RunnableExc { void run() throws Exception; }
@SuppressWarnings("unchecked")
private static void sneakyThrow(Throwable t) throws T {
throw (T) t;
}
IOException即使collect沒有聲明,你也可能會被扔到臉上。在大多數(但不是全部)實際情況下,無論如何,你都隻想抛出異常,并将其作為一般故障進行處理。在所有這些情況下,清晰度或正确性都不會丢失。隻是要提防那些其他情況,你實際上想在現場對異常做出反應。編譯器不會使開發人員意識到存在一個IOException陷阱,實際上,如果你嘗試捕獲它,編譯器實際上會抱怨,因為我們欺騙了它以為不會抛出此類異常。
2020-03-15