这种用于处理Java中的IO异常的模式是否正确?

时间:2013-11-29 11:43:58

标签: java io

在下面的代码片段中,如果抛出ex1,将被第二个catch块捕获,还是会被抛回到方法的调用者?

如果它被抛回到调用者,然后在finally块(ex2)中发生第二个异常,这是否意味着2个异常将被抛回调用者(ex1和ex2)?

try {
  // write to file
} catch (IOException ex1) {
  throw ex1;
} finally {
  try {
    aBufferedWriter.close();
  } catch (IOException ex2) {
    throw ex2;
  }
}

4 个答案:

答案 0 :(得分:6)

这两个例外都将被抛回调用者......虽然在任何特定情况下都是一个例外。如果外部try块的主体抛出然后close抛出,则调用者只能看到第二个异常。

然而,仅仅重新抛出catch块是毫无意义的。您的代码将更加清晰:

try {
  // write to file
} finally {
  aBufferedWriter.close();
}

在Java 7中,try-with-resources statement可以自动执行此操作:

try (BufferedWriter writer = new BufferedWriter(...)) {
    // Use the writer here
} // The writer is auto-closed here

通过这种方式,您可以 使用Throwable.getSuppressed与主体中的异常分开关闭异常。

答案 1 :(得分:0)

取决于设计。你也可以尝试

try{
    try{
      //write to file
    }finally{
       aBufferedWriter.close();
    }
}catch(IOException e){
}

如果你想抛出异常,也可以抓住异常。

答案 2 :(得分:0)

  

Q值。在下面的代码片段中,如果抛出ex1,将被第二个catch块捕获,还是会被抛回到方法的调用者?

不,它不会被catch内的finally块捕获,只要finally块中没有异常,因此异常ex1将被抛回调用方法。


  

Q值。如果它被抛回到调用者,然后在finally块(ex2)中发生第二个异常,这是否意味着2个异常将被抛回调用者(ex1和ex2)?

在这种情况下,由于在finally块中抛出异常,它将覆盖外部catch块中抛出的异常,并导致异常ex2被抛回调用方法。

只有一个异常会被抛回到调用方法中以便单次执行,而不是两者。话虽如此,拥有一个catch块只是为了抛弃已被捕获的异常,实在是毫无意义。

答案 3 :(得分:0)

在Java 7之前,真正准确的模式是

public void writeToFile(String file) throws IOException {
    IOException exception = null;
    OutputStream out = new FileOutputStream(file);
    try {
        // TODO: write data to file
    } catch (IOException ex) {
        // store exception for later rethrow
        exception = ex;
    } finally {
        try {
            out.close();
        } catch (IOException ex) {
            // do NOT supress 'outer' exception:
            if (exception == null) {
                exception = ex;
            }
        }
    }

    if (exception != null) {
        throw exception;
    }
}

看起来很疯狂,但这涵盖了所有可能性并绕过异常抑制异常(当finally语句中抛出异常时,它会抑制try块中发生的'真正'异常 - 如果有)。

但也许 - 为了便于阅读 - 你可以忍受被抑制的异常,并按照这样做:

OutputStream out = new FileOutputStream(file);
try {
    // TODO: write data to file
} finally {
    out.close(); // if an exception is thrown here, it hides the original exception
}

另见http://tutorials.jenkov.com/java-exception-handling/exception-handling-templates.html

从Java 7 开始,您可以使用try-with-resource语句(几乎)执行相同操作:

public void writeToFile(String file) throws IOException {
    try (OutputStream out = new FileOutputStream(file)) {
    // TODO: write data to file
    }
}

请注意,关闭资源时抛出的异常不会抑制原始异常。而是将这些额外的异常作为“抑制异常”添加到基本异常中。您可以使用baseException.getSuppressed()(Java 7及更高版本)获取它们。

另见http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html