如何将异常的集合作为根本原因传递?

gst*_*low 44 java spring exception spring-batch

某种方法myMethod调用多个并行执行并等待其终止。

这些并行执行可以例外完成。因此myMethod获得一个例外列表。

我想将异常列表作为根本原因进行传递,但根本原因可能只是单个异常。当然,我可以创建自己的异常来实现所需的功能,但是我想知道Java,Spring或Spring Batch是否具有类似这样的功能。

T.J*_*der 41

我不确定是否会这样做(尽管考虑到JavaDoc,我无法告诉您为什么要犹豫),但是其中包含抑制的异常列表Throwable,您可以将其添加到via中addSuppressed。JavaDoc似乎并没有说这只是供JVM在try-with-resources中使用:

将指定的异常附加到为了传递此异常而被抑制的异常。此方法是线程安全的,通常由try-with-resources语句(自动和隐式)调用。

除非通过构造函数禁用抑制行为,否则将启用抑制行为。禁用抑制后,此方法除了验证其参数外不执行其他操作。

请注意,当一个异常导致另一个异常时,通常会捕获第一个异常,然后作为响应抛出第二个异常。换句话说,两个例外之间存在因果关系。相反,在某些情况下,可能在同级代码块中引发两个独立的异常,特别是在try-with-resources语句的try块和编译器生成的finally块中,这两个异常会关闭资源。在这些情况下,只能传播引发的异常之一。在try-with-resources语句中,当有两个这样的异常时,将传播来自try块的异常,并将finally块的异常添加到由try块的异常抑制的异常列表中。作为例外,堆栈会散开,

异常可能抑制了异常,也可能是由另一个异常引起的。在创建异常时,从语义上知道异常是否有原因,这与异常是否会抑制其他异常不同,后者通常仅在引发异常后才能确定。

请注意,在有多个同级异常并且只能传播一个的情况下,程序员编写的代码也可以利用调用此方法的优势。

请注意,最后一段似乎很适合您的情况。


Joa*_*uer 22

异常及其原因始终只是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);
}
Run Code Online (Sandbox Code Playgroud)

  • 我不会按照您的建议那样做,除非可以将潜在的例外之一真正选作“主要”例外。如果您只是随意选择一个例外作为主要例外,而将其他例外作为被禁止例外,则您是_inviting_呼叫者忽略被阻止的例外并仅报告主要例外—即使“主要”例外是TypoInUserInputException并且其中一个被抑制的是DatabaseCorruptedException。 (4认同)