Java 在 catch 和 finally 子句中抛出异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3779285/
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
Exception thrown in catch and finally clause
提问by Jubstuff
On a question for Java at the university, there was this snippet of code:
关于大学的 Java 问题,有一段代码:
class MyExc1 extends Exception {}
class MyExc2 extends Exception {}
class MyExc3 extends MyExc2 {}
public class C1 {
public static void main(String[] args) throws Exception {
try {
System.out.print(1);
q();
}
catch (Exception i) {
throw new MyExc2();
}
finally {
System.out.print(2);
throw new MyExc1();
}
}
static void q() throws Exception {
try {
throw new MyExc1();
}
catch (Exception y) {
}
finally {
System.out.print(3);
throw new Exception();
}
}
}
I was asked to give its output. I answered 13Exception in thread main MyExc2
, but the correct answer is 132Exception in thread main MyExc1
. Why is it that? I just can't understand where does MyExc2
go.
我被要求提供它的输出。我回答了13Exception in thread main MyExc2
,但正确的答案是132Exception in thread main MyExc1
。为什么会这样?我就是不明白MyExc2
去哪里了。
采纳答案by Bert F
Based on reading your answer and seeing how you likely came up with it, I believe you think an "exception-in-progress" has "precedence". Keep in mind:
根据阅读您的答案并了解您可能如何想出它,我相信您认为“正在进行的异常”具有“优先级”。记住:
When an new exception is thrown in a catch block or finally blockthat will propagate out of that block, then the current exception will be aborted (and forgotten) as the new exception is propagated outward. The new exception starts unwinding up the stack just like any other exception, aborting out of the current block (the catch or finally block) and subject to any applicable catch or finally blocks along the way.
当在catch 块或 finally 块中抛出新异常并将传播出该块时,当前异常将随着新异常向外传播而被中止(并忘记)。新异常开始像任何其他异常一样展开堆栈,从当前块(catch 或 finally 块)中止并在此过程中受到任何适用的 catch 或 finally 块的影响。
Note that applicable catch or finally blocksincludes:
请注意,适用的 catch 或 finally 块包括:
When a new exception is thrown in a catch block, the new exception is still subject to that catch's finally block, if any.
当在 catch 块中抛出新异常时,新异常仍受该 catch 的 finally 块(如果有)的约束。
Now retrace the execution remembering that, whenever you hit throw
, you should abort tracing the current exception and start tracing the new exception.
现在回溯执行,记住,无论何时点击throw
,都应该中止跟踪当前异常并开始跟踪新异常。
回答by Uwe Keim
I think you just have to walk the finally
blocks:
我认为你只需要走finally
块:
- Print "1".
finally
inq
print "3".finally
inmain
print "2".
- 打印“1”。
finally
在q
打印“3”。finally
在main
打印“2”。
回答by Alexander Pogrebnyak
Finally clause is executed even when exception is thrown from anywhere in try/catch block.
即使从 try/catch 块中的任何地方抛出异常,也会执行 finally 子句。
Because it's the last to be executed in the main
and it throws an exception, that's the exception that the callers see.
因为它是最后一个在 中执行main
并且抛出异常,这就是调用者看到的异常。
Hence the importance of making sure that the finally
clause does not throw anything, because it can swallow exceptions from the try
block.
因此确保finally
子句不抛出任何东西的重要性,因为它可以从try
块中吞下异常。
回答by Buhake Sindi
This is what Wikipediasays about finally clause:
这是维基百科关于 finally 子句的说法:
More common is a related clause (finally, or ensure) that is executed whether an exception occurred or not, typically to release resources acquired within the body of the exception-handling block.
更常见的是无论是否发生异常都会执行相关子句(finally 或 ensure),通常是为了释放在异常处理块的主体内获取的资源。
Let's dissect your program.
让我们剖析您的程序。
try {
System.out.print(1);
q();
}
So, 1
will be output into the screen, then q()
is called. In q()
, an exception is thrown. The exception is then caught by Exception y
but it does nothing. A finallyclause is then executed (it has to), so, 3
will be printed to screen. Because (in method q()
there's an exception thrown in the finallyclause, also q()
method passes the exception to the parent stack (by the throws Exception
in the method declaration) new Exception()
will be thrown and caught by catch ( Exception i )
, MyExc2
exception will be thrown (for now add it to the exception stack), but a finallyin the main
block will be executed first.
所以,1
将被输出到屏幕,然后q()
被调用。在q()
,抛出异常。然后异常被捕获,Exception y
但它什么也不做。甲最后然后子句被执行(它有),所以,3
将被打印到屏幕。因为(在方法中q()
有一个异常在finally子句中抛出,并且q()
方法将异常传递到父堆栈(通过throws Exception
方法声明中)new Exception()
将被抛出并被捕获catch ( Exception i )
,MyExc2
异常将被抛出(现在将其添加到异常堆栈),但最后在main
块将被首先执行。
So in,
所以在,
catch ( Exception i ) {
throw( new MyExc2() );
}
finally {
System.out.print(2);
throw( new MyExc1() );
}
A finallyclause is called...(remember, we've just caught Exception i
and thrown MyExc2
) in essence, 2
is printed on screen...and after the 2
is printed on screen, a MyExc1
exception is thrown. MyExc1
is handled by the public static void main(...)
method.
一个最后条款被称为...(请记住,我们只是抓住了Exception i
,扔MyExc2
)在本质上,2
是印在屏幕上......而之后2
被显示在屏幕上,一个MyExc1
异常被抛出。MyExc1
由public static void main(...)
方法处理。
Output:
输出:
"132Exception in thread main MyExc1"
“线程主 MyExc1 中的 132Exception”
Lecturer is correct! :-)
老师说得对!:-)
In essence, if you have a finallyin a try/catch clause, a finally will be executed (aftercatching the exception beforethrowing the caught exception out)
本质上,如果你在 try/catch 子句中有一个finally,一个 finally 将被执行(在捕获异常之后,然后将捕获的异常抛出出去)
回答by Garis M Suero
A method
can't throw
two exceptions at the same time. It will always throw the last thrown exception
, which in this case it will be always the one from the finally
block.
Amethod
不能同时出现throw
两个异常。它将始终抛出最后一个 throw exception
,在这种情况下,它将始终是finally
块中的那个。
When the first exception from method q()
is thrown, it will catch'ed and then swallowed by the finally block thrown exception.
当方法q()
抛出第一个异常时,它会被捕获,然后被 finally 块抛出的异常吞下。
q() ->thrown new Exception
->main
catch Exception
->throw
new Exception
->finally
throw a new exception
(and the one from the catch
is "lost")
q() ->抛出new Exception
-> main
catch Exception
-> throw
new Exception
->finally
抛出一个新的exception
(其中一个catch
是“丢失”的)
回答by CodingWithSpike
The easiest way to think of this is imagine that there is a variable global to the entire application that is holding the current exception.
想到这一点的最简单方法是想象有一个全局变量对整个应用程序持有当前异常。
Exception currentException = null;
As each exception is thrown, "currentException" is set to that exception. When the application ends, if currentException is != null, then the runtime reports the error.
当抛出每个异常时,“currentException”被设置为该异常。当应用程序结束时,如果 currentException 为 != null,则运行时报告错误。
Also, the finally blocks always run before the method exits. You could then requite the code snippet to:
此外,finally 块总是在方法退出之前运行。然后,您可以将代码片段返回到:
public class C1 {
public static void main(String [] argv) throws Exception {
try {
System.out.print(1);
q();
}
catch ( Exception i ) {
// <-- currentException = Exception, as thrown by q()'s finally block
throw( new MyExc2() ); // <-- currentException = MyExc2
}
finally {
// <-- currentException = MyExc2, thrown from main()'s catch block
System.out.print(2);
throw( new MyExc1() ); // <-- currentException = MyExc1
}
} // <-- At application exit, currentException = MyExc1, from main()'s finally block. Java now dumps that to the console.
static void q() throws Exception {
try {
throw( new MyExc1() ); // <-- currentException = MyExc1
}
catch( Exception y ) {
// <-- currentException = null, because the exception is caught and not rethrown
}
finally {
System.out.print(3);
throw( new Exception() ); // <-- currentException = Exception
}
}
}
The order in which the application executes is:
应用程序执行的顺序是:
main()
{
try
q()
{
try
catch
finally
}
catch
finally
}
回答by Vouze
I think this solve the problem :
我认为这可以解决问题:
boolean allOk = false;
try{
q();
allOk = true;
} finally {
try {
is.close();
} catch (Exception e) {
if(allOk) {
throw new SomeException(e);
}
}
}
回答by Sly
It is well known that the finally block is executed after the the try and catch and is always executed.... But as you saw it's a little bit tricky sometimes check out those code snippet below and you will that the return and throw statements don't always do what they should do in the order that we expect theme to.
众所周知,finally 块是在 try 和 catch 之后执行的,并且总是被执行......但是正如你所看到的,有时检查下面的代码片段有点棘手,你会发现 return 和 throw 语句不会不要总是按照我们期望主题的顺序做他们应该做的事情。
Cheers.
干杯。
/////////////Return dont always return///////
try{
return "In Try";
}
finally{
return "In Finally";
}
////////////////////////////////////////////
////////////////////////////////////////////
while(true) {
try {
return "In try";
}
finally{
break;
}
}
return "Out of try";
///////////////////////////////////////////
///////////////////////////////////////////////////
while (true) {
try {
return "In try";
}
finally {
continue;
}
}
//////////////////////////////////////////////////
/////////////////Throw dont always throw/////////
try {
throw new RuntimeException();
}
finally {
return "Ouuuups no throw!";
}
//////////////////////////////////////////////////
回答by Roland
Exceptions in the finally block supersede exceptions in the catch block.
finally 块中的异常取代了 catch 块中的异常。
Quoting from the Java Language Specification 14 edition:
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 被丢弃)。
回答by Luiz Fernando
class MyExc1 extends Exception {}
class MyExc2 extends Exception {}
class MyExc3 extends MyExc2 {}
public class C1 {
public static void main(String[] args) throws Exception {
try {
System.out.print("TryA L1\n");
q();
System.out.print("TryB L1\n");
}
catch (Exception i) {
System.out.print("Catch L1\n");
}
finally {
System.out.print("Finally L1\n");
throw new MyExc1();
}
}
static void q() throws Exception {
try {
System.out.print("TryA L2\n");
q2();
System.out.print("TryB L2\n");
}
catch (Exception y) {
System.out.print("Catch L2\n");
throw new MyExc2();
}
finally {
System.out.print("Finally L2\n");
throw new Exception();
}
}
static void q2() throws Exception {
throw new MyExc1();
}
}
Order:
命令:
TryA L1
TryA L2
Catch L2
Finally L2
Catch L1
Finally L1
Exception in thread "main" MyExc1 at C1.main(C1.java:30)