未捕获 Java 异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18097496/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java exception not caught?
提问by Kousalik
I have a small theoreticalproblem with try-catch constructions.
我有一个关于 try-catch 结构的小理论问题。
I took a practical exam yesterday about Java and I don't understand following example:
我昨天参加了关于 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());
}
The question was "what the output will look like?"
问题是“输出会是什么样子?”
I was pretty sure it would be AB2C3, BUT suprise suprise, it's not true.
我很确定它会是 AB2C3,但很惊讶,这不是真的。
The right answer is ABC3 (tested and really it's like that).
正确答案是 ABC3(经过测试,确实如此)。
My question is, where did the Exception("2") go?
我的问题是,Exception("2") 到哪里去了?
采纳答案by Adam Siemion
From the Java Language Specification 14.20.2.:
If the catch block completes abruptly for reason R, then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly for reason R.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
如果 catch 块由于原因 R 突然完成,则执行 finally 块。然后有一个选择:
如果 finally 块正常完成,则 try 语句由于原因 R 突然完成。
如果 finally 块因 S 原因突然完成,则 try 语句因 S 原因突然完成(并且 R 被丢弃)。
So, when there is a catch block that throws an exception:
所以,当有一个抛出异常的 catch 块时:
try {
// ...
} catch (Exception e) {
throw new Exception("2");
}
but there is also a finally block that also throws an exception:
但还有一个 finally 块也会引发异常:
} finally {
throw new Exception("3");
}
Exception("2")
will be discarded and only Exception("3")
will be propagated.
Exception("2")
将被丢弃,只会Exception("3")
被传播。
回答by S.D.
Exceptions thrown in finally block suppress the exception thrown earlier in try or catch block.
finally 块中抛出的异常会抑制之前在 try 或 catch 块中抛出的异常。
Java 7 example: http://ideone.com/0YdeZo
Java 7 示例:http: //ideone.com/0YdeZo
From Javadoc'sexample:
从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();
}
}
However, in this example, if the methods readLine and close both throw exceptions, then the method readFirstLineFromFileWithFinallyBlock throws the exception thrown from the finally block; the exception thrown from the try block is suppressed.
然而,在这个例子中,如果方法 readLine 和 close 都抛出异常,那么方法 readFirstLineFromFileWithFinallyBlock 抛出从 finally 块抛出的异常;从 try 块抛出的异常被抑制。
The new try-with
syntax of Java 7 adds another step of exception suppression: Exceptions thrown in try block suppress those thrown earlier in try-with part.
try-with
Java 7的新语法添加了另一个异常抑制步骤:在 try 块中抛出的异常会抑制在 try-with 部分中早期抛出的异常。
from same example:
来自同一个例子:
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());
}
}
An exception can be thrown from the block of code associated with the try-with-resources statement. In the above example, an exception can be thrown from the try block, and up to two exceptions can be thrown from the try-with-resources statement when it tries to close the ZipFile and BufferedWriter objects. If an exception is thrown from the try block and one or more exceptions are thrown from the try-with-resources statement, then those exceptions thrown from the try-with-resources statement are suppressed, and the exception thrown by the block is the one that is thrown by the writeToFileZipFileContents method. You can retrieve these suppressed exceptions by calling the Throwable.getSuppressed method from the exception thrown by the try block.
可以从与 try-with-resources 语句关联的代码块中抛出异常。在上面的示例中,可以从 try 块中抛出异常,并且在尝试关闭 ZipFile 和 BufferedWriter 对象时,try-with-resources 语句最多可以抛出两个异常。如果从 try 块抛出异常,并且 try-with-resources 语句抛出一个或多个异常,那么这些从 try-with-resources 语句抛出的异常将被抑制,并且块抛出的异常是由 writeToFileZipFileContents 方法抛出。您可以通过从 try 块抛出的异常中调用 Throwable.getSuppressed 方法来检索这些被抑制的异常。
In code from question, each block is plainly discarding the old exception, not even logging it, not good when you are trying to resolve some bugs:
在有问题的代码中,每个块都明显地丢弃了旧的异常,甚至不记录它,这在您尝试解决一些错误时并不好:
回答by Maroun
Since throw new Exception("2");
is thrown from catch
block and not try
, it won't be caught again.
See 14.20.2. Execution of try-finally and try-catch-finally.
由于throw new Exception("2");
是从catch
块中抛出而不是try
,因此不会再次被捕获。
见14.20.2。执行 try-finally 和 try-catch-finally。
This is what happening:
这是正在发生的事情:
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
}
回答by allprog
The finally
block always runs. Either you return
from inside the try block or an exception is thrown. The exception thrown in the finally
block will override the one thrown in the catch branch.
该finally
块始终运行。要么你return
来自 try 块,要么抛出异常。finally
块中抛出的异常将覆盖 catch 分支中抛出的异常。
Additionally, throwing an exception will not cause any output by itself. The line throw new Exception("2");
will not write anything out.
此外,抛出异常本身不会导致任何输出。该行throw new Exception("2");
不会写出任何内容。
回答by Bharat
Your Question is very obvious, and the answer is simple to the same extent.. The Exception object with message as "2" is overwritten by the Exception object with message as "3" .
您的问题非常明显,答案也很简单。 消息为 "2" 的 Exception 对象被消息为 "3" 的 Exception 对象覆盖。
Explanation :When an Exception occur, its object it thrown to catch block to handle. But when exception occur in catch block itself, its object is transferred to OUTER CATCH Block(if any) for exception Handling. And Same happened Here. The Exception Object with message "2" is transferred to OUTER catch Block . But wait.. Before leaving inner try-catch block it HAS TO EXECUTE FINALLY. Here occurred the change we are concerned about. A new EXCEPTION object(with message "3") is thrown out or this finally block which replaced the already thrown Exception object(with message "2").As a result of which, when the message of Exception object is printed , we got overridden value i.e. "3" and not "2".
说明:当异常发生时,它抛出的对象到catch块来处理。但是当异常发生在 catch 块本身时,它的对象被转移到 OUTER CATCH 块(如果有)进行异常处理。同样发生在这里。带有消息“2”的异常对象被传输到 OUTER catch Block 。但是等等.. 在离开内部 try-catch 块之前,它必须最终执行。这里发生了我们所关心的变化。一个新的异常对象(带有消息“3”)被抛出,或者这个 finally 块替换了已经抛出的异常对象(带有消息“2”)。因此,当打印异常对象的消息时,我们得到覆盖值,即“3”而不是“2”。
Keep Remember :Only one exception object can be handled by on CATCH block.
请记住:在 CATCH 块上只能处理一个异常对象。
回答by nazar_art
According to your code:
根据您的代码:
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());
}
As you can see here:
正如你在这里看到的:
- print A and throws exception
# 1
; - this exception has caught by catch statement and print
B - # 2
; - block finally
# 3
executes after try-catch (or only try, if hadn't occurred any exception) statement and printsC - # 4
and thrown new exception; - this one has caught by external catch statement
# 5
;
- 打印 A 并抛出异常
# 1
; - 此异常已被 catch 语句和打印捕获
B - # 2
; - 块最终
# 3
在 try-catch (或仅尝试,如果没有发生任何异常)语句后执行并打印C - # 4
并抛出新异常; - 这个已经被外部 catch 语句捕获了
# 5
;
Result is ABC3
. And 2
is omitted at the same way as 1
结果是ABC3
。并2
以相同的方式省略1