Java 8 - 在 lambda 中抛出多个通用检查异常

标签 java lambda java-8 exception-handling

在我正在从事的一个项目中,我发现了一个类,该类将其父类(super class)的所有方法包装在一些精心设计的异常处理中。它看起来类似于:

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 添加更多通用参数,但它没有改变任何东西。

如何获得一个函数式接口(interface)来处理多个通用异常?

最佳答案

当您扩展接口(interface)以使用两个类型变量时,即

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

这是您可以通过这种方法获得的最佳效果。

关于Java 8 - 在 lambda 中抛出多个通用检查异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52558214/

相关文章:

amazon-web-services - 为什么通过Chalice的Lambda API会给出内部服务器错误而不是datetime值?

java - 将 map 转换为列表<string> - 作为每个列表条目的 "key-value"

java - 获取数字流的范围

java - 使用 Java 的 File.delete() 方法

java - 如何正确配置这个Camel路由xml?

python - 实例化类、调用其方法之一并从 lambda 函数返回它的 pythonic 方式是什么?

ruby - `[]` 如何与 lambda 一起使用

java - 尝试使用 Netbeans 8.0 在 javadoc 注释中的 {@code} block 中转义 "@"符号

java - 在 java 中使用 Arrays.asList 的协方差?

Java按空格分隔行读取并插入到树中