【发布时间】:2019-03-04 14:54:59
【问题描述】:
在我正在从事的一个项目中,我发现了一个类,它在一些复杂的异常处理中包装了它的超类的所有方法。它看起来类似于:
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 添加更多通用参数,但没有任何改变。
如何获得一个功能接口来处理多个通用异常?
【问题讨论】:
-
我想说的问题之一是您的
wrapMethod()需要在其 throws 子句中支持多个异常,以便像在method2()中那样调用它并抛出 @987654328 @ 和/或ExceptionC。因此,您可能需要为多个异常提供重载(可能不会那么多,因为 IMO 的 throws 子句中有 20 个异常的方法无论如何都是不好的设计)。由于您需要多个wrapMethod(),因此您可能需要将转换和日志记录部分提取到单独的方法中 - 如果可能的话。 -
@Thomas 我尝试了 5 个通用异常而不是 1 个的方法。它没有改变任何事情。包装
method1仍然有效,包装method2仍然默认为Exception。所以它不会起作用,除非你建议我应该为每个可能的异常数量创建一个单独的包装器,但这会破坏这个练习的要点,即使代码更短。 -
你应该清理语法。这是
interface ThrowingMethod<E extends Exception>,而不是interface <E extends Exception> ThrowingMethod。此外,无需将接口声明为static。这总是暗示的。 -
好吧,如果你所有的方法都有不同数量的异常抛出,那么是的,这个练习没有实际意义。如果不是,那么它可能仍然值得,特别是因为接口声明不是那么大,并且可以提取到单独的文件中(并且在其他情况下也可以重用)。
-
@M.Prokhorov 和
javac没有区别
标签: java lambda java-8 exception-handling