某种方法myMethod
调用多个并行执行并等待其终止。
这些并行执行可以例外完成。因此myMethod
获得一个例外列表。
我想将异常列表作为根本原因传递,但是根本原因可能只是单个异常。当然,我可以创建自己的异常来实现所需的功能,但是我想知道Java,Spring或Spring Batch是否具有类似这样的功能。
某种方法myMethod
调用多个并行执行并等待其终止。
这些并行执行可以例外完成。因此myMethod
获得一个例外列表。
我想将异常列表作为根本原因传递,但是根本原因可能只是单个异常。当然,我可以创建自己的异常来实现所需的功能,但是我想知道Java,Spring或Spring Batch是否具有类似这样的功能。
Answers:
我不确定是否会这样做(尽管考虑到JavaDoc,我无法告诉您为什么要犹豫),但是其中包含抑制的异常列表Throwable
,您可以将其添加到via中addSuppressed
。JavaDoc似乎并没有说这只是供JVM在try-with-resources中使用:
将指定的异常附加到为了传递此异常而被抑制的异常。此方法是线程安全的,通常由try-with-resources语句(自动和隐式)调用。
除非通过构造函数禁用抑制行为,否则将启用抑制行为。禁用抑制后,此方法除了验证其参数外不执行其他操作。
请注意,当一个异常导致另一个异常时,通常会捕获第一个异常,然后作为响应抛出第二个异常。换句话说,两个例外之间存在因果关系。相反,在某些情况下,可能在同级代码块中引发两个独立的异常,特别是在try-with-resources语句的try块和编译器生成的finally块中,这两个异常会关闭资源。在这些情况下,只能传播所引发的异常之一。在try-with-resources语句中,当有两个这样的异常时,将传播来自try块的异常,并将finally块的异常添加到由try块的异常抑制的异常列表中。作为例外,堆栈会散开,
异常可能抑制了异常,也可能是由另一个异常引起的。在创建异常时,从语义上知道异常是否有原因,这与异常是否会抑制其他异常(通常仅在引发异常后才确定)不同。
请注意,在存在多个同级异常并且只能传播一个的情况下,程序员编写的代码也可以利用调用此方法的优势。
请注意,最后一段似乎很适合您的情况。
异常及其原因始终只是1:1的事情:您可以引发一个异常,并且每个异常只能有一个原因(又可以有一个原因...)。
可以将其视为设计错误,尤其是在考虑到您所描述的多线程行为时。
这就是为什么Java 7添加addSuppressed
到throwable 的原因之一,它基本上可以将任意数量的异常附加到其他单个异常上(另一个主要动机是try-with-resources,它需要一种方法来处理finally块中的异常而不会无声地删除他们)。
因此,基本上,当您有1个导致流程失败的异常时,可以将该原因添加为更高级别异常的原因,如果有更多异常,则可以使用将该异常添加到原始异常中addSuppressed
。这个想法是,第一个异常“压制”其他异常成为“真正的异常链”的成员。
样例代码:
Exception exception = null;
for (Foobar foobar : foobars) {
try {
foobar.frobnicate();
} catch (Exception ex) {
if (exception == null) {
exception = ex;
} else {
exception.addSuppressed(ex);
}
}
}
if (exception != null) {
throw new SomethingWentWrongException(exception);
}
AggregateException
包含例外列表的。这个想法也应该适用于Java。