Kou*_*lik 170 java exception try-catch
我对try-catch构造有一个小的理论问题.
我昨天参加了一个关于Java的实践考试,我不明白以下例子:
try {
try {
System.out.print("A");
throw new Exception("1");
} catch (Exception e) {
System.out.print("B");
throw new Exception("2");
} finally {
System.out.print("C");
throw new Exception("3");
}
} catch (Exception e) {
System.out.print(e.getMessage());
}
Run Code Online (Sandbox Code Playgroud)
问题是"输出会是什么样子?"
我很确定它会是AB2C3,但令人惊讶的是,这不是真的.
正确的答案是ABC3(经过测试,确实就是这样).
我的问题是,例外("2")去了哪里?
Ada*_*ion 196
如果catch块由于原因R突然完成,则执行finally块.然后有一个选择:
如果finally块正常完成,则try语句突然完成,原因是R.
如果finally块由于原因S而突然完成,则try语句突然完成,原因S(并且原因R被丢弃).
所以,当有一个引发异常的catch块时:
try {
// ...
} catch (Exception e) {
throw new Exception("2");
}
Run Code Online (Sandbox Code Playgroud)
但是还有一个finally块也会引发异常:
} finally {
throw new Exception("3");
}
Run Code Online (Sandbox Code Playgroud)
Exception("2")将被丢弃,只会Exception("3")传播.
S.D*_*.D. 19
finally块中抛出的异常会抑制先前在try或catch块中抛出的异常.
Java 7示例:http://ideone.com/0YdeZo
从Javadoc的例子:
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,在此示例中,如果方法readLine和close都抛出异常,则方法readFirstLineFromFileWithFinallyBlock抛出finally块抛出的异常; 从try块抛出的异常被抑制.
try-withJava 7 的新语法增加了另一个异常抑制步骤:try块中抛出的异常会抑制try-with part中之前抛出的异常.
来自同一个例子:
try (
java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) {
String newLine = System.getProperty("line.separator");
String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
Run Code Online (Sandbox Code Playgroud)
可以从与try-with-resources语句关联的代码块中抛出异常.在上面的示例中,可以从try块抛出异常,并且当try-with-resources语句尝试关闭ZipFile和BufferedWriter对象时,最多可以抛出两个异常.如果从try块抛出异常并且从try-with-resources语句抛出了一个或多个异常,那么从try-with-resources语句抛出的那些异常将被抑制,并且块抛出的异常是这是由writeToFileZipFileContents方法抛出的.您可以通过从try块抛出的异常中调用Throwable.getSuppressed方法来检索这些抑制的异常.
在问题的代码中,每个块明显地丢弃旧的异常,甚至没有记录它,当你试图解决一些错误时不好:
http://en.wikipedia.org/wiki/Error_hiding
既然throw new Exception("2");是从catch块而不是被抛出try,它将不再被捕获.
见14.20.2.执行try-finally和try-catch-finally.
这就是发生的事情:
try {
try {
System.out.print("A"); //Prints A
throw new Exception("1");
} catch (Exception e) {
System.out.print("B"); //Caught from inner try, prints B
throw new Exception("2");
} finally {
System.out.print("C"); //Prints C (finally is always executed)
throw new Exception("3");
}
} catch (Exception e) {
System.out.print(e.getMessage()); //Prints 3 since see (very detailed) link
}
Run Code Online (Sandbox Code Playgroud)
您的问题非常明显,答案在相同程度上也很简单。 消息为“ 2”的Exception对象被消息为“ 3”的Exception对象覆盖。
说明: 发生异常时,抛出它的对象以捕获块以进行处理。但是,当catch块本身发生异常时,其对象将转移到OUTER CATCH Block(如果有)以进行异常处理。同样发生在这里。消息为“ 2”的异常对象将传输到OUTER catch Block。但是,请等待 ..在离开内部try-catch块之前,它必须最终执行。这里发生了我们关注的变化。抛出了一个新的EXCEPTION对象(带有消息“ 3”),或者此finally块替换了已经抛出的Exception对象(带有消息“ 2”)。结果,当打印Exception对象的消息时,我们得到了覆盖值,即“ 3”而不是“ 2”。
请记住:CATCH块只能处理一个异常对象。
| 归档时间: |
|
| 查看次数: |
16176 次 |
| 最近记录: |