如何避免异常阴影?

cev*_*ing 9 java exception

在处理异常过程中发生异常时,只会报告最后一个异常,因为我只能向Error对象添加一个异常。如何在最终错误消息中报告所有异常?

例子:

class main
{
  public static void main (String[] args)
  {
    try {
      // Database.insert ();
      throw new Exception ("insert failed");
    }
    catch (Exception ex1) {
      try {
        // Database.rollback ();
        throw new Exception ("rollback failed");
      }
      catch (Exception ex2) {
        throw new Error ("Can not roll back transaction.", ex2);
      }
    }
    finally {
      try {
        // Database.close ();
        throw new Exception ("close failed");
      }
      catch (Exception ex3) {
        throw new Error ("Can not close database.", ex3);
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在示例中,一切都失败了。数据库插入导致ex1. 回滚导致ex2. 和关闭数据库的原因ex3。当程序被执行时,只有最后一个ex3被报告在Error对象中。如何还包括ex1ex2Error对象?的构造函数Error只接受一个异常。

Lin*_*ica 12

我建议您将Java 7 中引入的try-with-resource -statements-interface 结合使用AutoCloseable

旁注Connection,StatementResultSet来自java.sql所有实现AutoCloseable

try (Connection c = DriverManager.getConnection(url)) {
    // do your inserts
} catch (Exception e) {
    throw new Error("Insert failed", e);
}
Run Code Online (Sandbox Code Playgroud)

这将适当地关闭您的connection或通常通过的AutoCloseable。并且将通过使用该Throwable.addSuppressed()方法来处理异常的阴影。

另一个问题上可以看到以前版本中的等效内容


您的问题还提到了我没有涵盖的回滚。这可以通过使用前面提到的Throwable.addSuppressed()方法来完成(正如tobias_k的评论中指出的那样),但老实说它变得更加混乱,并且看起来不再那么好:

Exception insertException = null;
try (Connection c = DriverManager.getConnection(url)) {
    try {
        // do your inserts
    } catch (Exception e1) {
        insertException = e1;
        // do your rollback
    }
} catch (Exception e2) {
    Error error = new Error("Insert failed", insertException);
    error.addSuppressed(e2);
    throw error;
}
Run Code Online (Sandbox Code Playgroud)

只是为了澄清,内部catch块,只能在插入失败时到达。当以下任何一个抛出异常catch时,可以到达外部的地方:

  • DriverManager.getConnection()
  • 你的回滚
  • Connection.close()

对于一个小演示,您可以访问此链接,它说明了堆栈跟踪的样子。