[英]Java 8 - throw multiple generic checked exceptions in lambda
在我正在工作的項目中,我找到了一個類,它在一些精心設計的異常處理中包裝了它的超類的所有方法。 它看起來類似於:
public void method1() throws ExceptionA {
String exceptionString = "";
try {
super.method1();
} catch (ExceptionA e) {
exceptionString = // <convert the exception to string in an elaborate way>
throw e;
} finally {
// <an elaborate logger call which uses value of exceptionString>
}
}
public void method2() throws ExceptionB, ExceptionC {
String exceptionString = "";
try {
super.method2();
} catch (ExceptionB | ExceptionC e) {
exceptionString = // <convert the exception to string in elaborate way>
throw e;
} finally {
// <an elaborate logger call which uses value of exceptionString>
}
}
// ... <a bunch of other methods like this>
我馬上就說“哇,怎么可能有一個通用的包裝器,只需在每個方法中調用它。這個類就會縮短10倍!”。 所以我開始工作了。
這是我被卡住的地方:
private interface ThrowingMethod<E extends Exception> {
void run() throws E;
}
public <E extends Exception> void wrapMethod(ThrowingMethod<E> method) throws E {
String exceptionString = "";
try {
method.run();
} catch (Exception e) {
exceptionString = // <convert the exception to string in an elaborate way>
throw e;
} finally {
// <an elaborate logger call which uses value of exceptionString>
}
}
public void method1() throws ExceptionA {
wrapMethod(super::method1); // works
}
public void method2() throws ExceptionB, ExceptionC {
wrapMethod(super::method2); // Error in Eclipse: "Unhandled exception type Exception"
}
// ... <a bunch of other methods like this>
總之,這種方法適用於僅拋出一種類型的已檢查異常的方法。 當方法拋出多個已檢查的異常時,Java假定異常類型為Exception
。
我試圖向ThrowingMethod
和wrapMethod
添加更多通用參數,但它不會改變任何東西。
如何獲得一個功能界面來處理多個通用異常?
當您擴展接口以使用兩個類型變量時,即
private static interface ThrowingMethod<E1 extends Exception,E2 extends Exception> {
void run() throws E1, E2;
}
public <E1 extends Exception,E2 extends Exception>
void wrapMethod(ThrowingMethod<E1,E2> method) throws E1,E2 {
// same as before
}
關於類型推斷的規則不會改變,並且它們對於兩個類型變量都是相同的。 例如,你仍然可以使用
public void method1() throws ExceptionA {
wrapMethod(super::method1);
}
和以前一樣,編譯器只是為兩個類型變量推斷出相同的單一異常類型。
對於聲明兩個異常的方法,它不會為第一個類型變量拾取一個,而為第二個變量拾取另一個; 沒有規則可以告訴編譯器哪個異常用於哪個類型變量。
但是在這種情況下你可以幫助編譯器,例如
public void method2() throws ExceptionB, ExceptionC {
wrapMethod((ThrowingMethod<ExceptionB, ExceptionC>)super::method2);
}
這是你用這種方法得到的最好的。
所以你的目標只是用日志包裝一堆方法? 處理此問題的典型方法是使用AOP 。 你只需創建一個匹配所有這些方法的切入點,你就不會有一堆重復的樣板。 不需要那些接口或包裝方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.