6

从 Java 7 开始,我们可以使用 try-with-resources 语句:

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

ifbr.readLine()br.close() both throw exceptions 都会readFirstLineFromFile从try中抛出异常( 的异常),并且try-with-resources 语句的隐式 finally 块中的异常( 的异常)将被抑制。br.readLine()br.close()

在这种情况下,我们可以通过从try 块的异常中调用方法来从隐式 finally 块中检索被抑制的异常,如下所示:getSuppresed

try {   
    readFirstLineFromFile("Some path here..."); // this is the method using try-with-resources statement
}   catch (IOException e) {     // this is the exception from the try block  
    Throwable[] suppressed = e.getSuppressed();
    for (Throwable t : suppressed) {
        // Check t's type and decide on action to be taken
    }
}

但是假设我们必须使用使用比 Java 7 更旧的版本编写的方法,其中使用了 finally 块:

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

那么如果br.readLine()br.close()一次都抛出异常,情况就会逆转。该方法readFirstLineFromFileWithFinallyBlock抛出finally 块的异常(的异常br.close()),而try 块的异常(的异常br.readLine())将被抑制。

所以我的问题是:在第二种情况下,我们如何从try 块中检索抑制的异常?

来源:http ://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

4

2 回答 2

6

你不能,基本上。如果br.close()抛出,被抑制的异常会丢失。

您最接近的方法是拥有一个catch将值分配给 locla 变量的块:

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
    IOException exception = null;
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
      return br.readLine();
    } catch (IOException e) {
      exception = e;
    } finally {
      try {
        if (br != null) br.close();
      } catch (IOException e) {
        // Both the original call and close failed. Eek!
        // Decide what you want to do here...
      }
      // close succeeded, but we already had an exception
      if (exception != null) {
        throw exception;
      }
    }
}

...但这处理IOException(而不是任何未经检查的异常)并且非常混乱。

于 2013-05-10T11:35:59.643 回答
1

try 块的异常( br.readLine() 的异常)将被抑制。

这不太正确。Java 语言规范写道

  • 如果 try 块的执行由于抛出值 V 而突然完成,那么有一个选择:

    • 如果 V 的运行时类型与 try 语句的任何 catch 子句的可捕获异常类的赋值不兼容,则执行 finally 块。然后有一个选择:

      • 如果 finally 块正常完成,那么 try 语句会因为抛出值 V 而突然完成。

      • 如果 finally 块由于原因 S 突然完成,则 try 语句由于原因 S 突然完成(并且值 V 的抛出被丢弃并被遗忘)。

也就是说,异常被“丢弃和遗忘”,而不仅仅是被压制。

顺便说一句,由于 Java 7 中引入了将抑制的异常附加到另一个异常的机制,因此 Java 6 中没有对此的一般支持。因此,针对 Java 6 的代码无法利用该功能。

于 2013-05-10T11:46:16.897 回答