簡體   English   中英

Java 8 - 在lambda中拋出多個泛型檢查異常

[英]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

我試圖向ThrowingMethodwrapMethod添加更多通用參數,但它不會改變任何東西。

如何獲得一個功能界面來處理多個通用異常?

當您擴展接口以使用兩個類型變量時,即

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM