未捕获Java异常?
我对try-catch结构有一个理论上的小问题 昨天我参加了一个关于Java的实践考试,我不理解下面的例子:未捕获Java异常?,java,exception,try-catch,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 {
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());
}
问题是“输出将是什么样子?”
我很确定这是AB2C3,但令人惊讶的是,这不是真的
正确的答案是ABC3(经过测试,确实如此)
我的问题是,异常(“2”)去了哪里?在finally块中抛出的异常抑制了在try或catch块中先前抛出的异常 Java 7示例: 例如:
但是,在本例中,如果方法readLine和close都抛出 异常,则方法readFirstLineFromFileWithFinallyBlock 抛出从finally块抛出的异常;例外 禁止从try块抛出
Java7新的
try-with
语法添加了异常抑制的另一个步骤:try块中抛出的异常抑制前面在try-with部分中抛出的异常
从同一个例子:
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());
}
}
可以从与
尝试使用资源语句。在上面的示例中,可能会出现异常
可以从try块抛出,最多可以抛出两个异常
从尝试关闭时的try with resources语句
ZipFile和BufferedWriter对象。如果从
try块,并从
请尝试使用resources语句,然后从
try with resources语句被抑制,并引发异常
块旁边是由
writeToFileZipFileContents方法。您可以检索这些文件
通过从
try块引发的异常
在问题中的代码中,每个块都明显地丢弃了旧的异常,甚至没有记录它,当您试图解决一些bug时,这是不好的: 来自: 如果catch块由于原因R而突然完成,则执行finally块。还有一个选择:
- 如果finally块正常完成,那么try语句由于原因R而突然完成
- 如果finally块因原因S而突然完成,则try语句因原因S而突然完成(并且原因R被丢弃)
try {
// ...
} catch (Exception e) {
throw new Exception("2");
}
} finally {
throw new Exception("3");
}
但还有一个finally块也会引发异常:
try {
// ...
} catch (Exception e) {
throw new Exception("2");
}
} finally {
throw new Exception("3");
}
异常(“2”)
将被丢弃,并且只有异常(“3”)
将被传播。因为抛出新异常(“2”)代码>从catch
块抛出,而不是try
,它将不会被再次捕获。
请参见
事情就是这样:
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
}
finally
块始终运行。要么从try块内部返回,要么抛出异常。finally
块中抛出的异常将覆盖catch分支中抛出的异常
此外,引发异常本身不会导致任何输出。行抛出新异常(“2”)
不会写出任何东西。你的问题很明显,答案也很简单。。
消息为“2”的异常对象被消息为“3”的异常对象覆盖。
说明:
当异常发生时,它会将其对象抛出catch块来处理。但当catch块本身发生异常时,它的对象被转移到外部catch块(如果有)进行异常处理。这里也发生了同样的事情。带有消息“2”的异常对象被传输到外部catch块但请等待。。在离开内部try-catch块之前,它必须最终执行。这里发生了我们所关心的变化。抛出一个新的异常对象(带有消息“3”)或此finally块,该块替换了已抛出的异常对象(带有消息“2”)。因此,当打印异常对象的消息时,我们得到了覆盖值,即“3”,而不是“2”
请记住:on CATCH块只能处理一个异常对象。根据您的代码:
try {
try {
System.out.print("A");
throw new Exception("1"); // 1
} catch (Exception e) {
System.out.print("B"); // 2
throw new Exception("2");
} finally { // 3
System.out.print("C"); // 4
throw new Exception("3");
}
} catch (Exception e) { // 5
System.out.print(e.getMessage());
}
正如你在这里看到的:
打印并引发异常#1
李>
此异常捕获了catch语句并打印B-#2
李>
block finally#3
在try-catch(或者只有try,如果没有发生任何异常)语句之后执行,并打印C-#4
和抛出新异常李>
这一个已被外部catch语句捕获李>
结果是ABC3
。而2
的省略方式与1
相同,这甚至适用于return
语句。如果finally块有返回,它将覆盖try
或catch
块中的任何返回。由于这些“特性”,一个很好的实践是finally块不应该抛出异常或返回语句。这也是在Java7中使用资源try with resources所具有的继承优势。如果在关闭资源时生成辅助异常,它会保留初始异常,这通常会使调试更容易。是的,我看到了这种情况,但我正在寻找解释-为什么它会这样做是的,我知道自己不会抛出异常输出,但我不知道原因,为什么应该删除异常2。我又聪明了一点:-)总是很长的时间,在很长的时间内任何事情都可能发生(检查谜题)+1啊,伙计,我知道这个答案。我在一次采访中被问到这个问题。对于理解try/catch/finally如何在堆栈上工作来说,这是一个非常好的问题。只有一个print语句可以打印数字(最后一个:print(e.getMessag))