Java 中的finally 块总是被执行吗?
考虑到这段代码,我是否可以绝对确定 finally
块始终执行,无论 something()
是什么?
try {
something();
return success;
}
catch (Exception e) {
return failure;
}
finally {
System.out.println("I don't know if this will get printed out");
}
Considering this code, can I be absolutely sure that the finally
block always executes, no matter what something()
is?
try {
something();
return success;
}
catch (Exception e) {
return failure;
}
finally {
System.out.println("I don't know if this will get printed out");
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
是的,
finally
将在执行try
或catch
代码块后被调用。唯一不会调用
finally
的情况是:System.exit()
Runtime.getRuntime().halt(exitStatus)< /code>
try
或catch
块中达到无限循环(或其他一些不可中断、非终止语句)kill -9
finally
块将由守护线程执行,并且所有其他非守护线程在finally
之前退出叫做Yes,
finally
will be called after the execution of thetry
orcatch
code blocks.The only times
finally
won't be called are:System.exit()
Runtime.getRuntime().halt(exitStatus)
try
orcatch
blockkill -9 <pid>
on UNIXfinally
block is going to be executed by a daemon thread and all other non-daemon threads exit beforefinally
is called最后的返回也会抛出任何异常。 http://jamesjava.blogspot.com/2006/03 /dont-return-in-finally-clause.html
Also a return in finally will throw away any exception. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
finally
总是被执行,除非程序异常终止(比如调用System.exit(0)
)。 因此,您的System.out
将被打印。finally
is always executed unless there is abnormal program termination (like callingSystem. exit(0)
). so, yourSystem.out
will get printed.除非出现异常程序终止(由于 JVM 崩溃或调用
System.exit(0)
导致),否则 Final 块始终会执行。最重要的是,从finally块中返回的任何值都将覆盖执行finally块之前返回的值,因此在使用tryfinally时要小心检查所有退出点。
The finally block is always executed unless there is abnormal program termination, either resulting from a JVM crash or from a call to
System.exit(0)
.On top of that, any value returned from within the finally block will override the value returned prior to execution of the finally block, so be careful of checking all exit points when using try finally.
不,并非总是如此,一种例外情况是
System.exit(0);
在
finally
块之前阻止执行finally
。No, not always, one exception case is
System.exit(0);
before the
finally
block preventsfinally
to be executed.这就是finally 块的全部思想。 当然,它可以让您确保进行清理工作,否则这些清理工作可能会因为您返回而被跳过。
无论 try 块中发生什么,finally 都会被调用(除非您调用
System.exit(int)
或 Java 虚拟机退出其他一些原因)。That is the whole idea of a finally block. It lets you make sure you do cleanups that might otherwise be skipped because you return, among other things, of course.
Finally gets called regardless of what happens in the try block (unless you call
System.exit(int)
or the Java Virtual Machine kicks out for some other reason).思考这个问题的逻辑方法是:
A logical way to think about this is:
以下是凯文的回答的详细阐述。 重要的是要知道要返回的表达式是在
finally
之前计算的,即使它是在之后返回的。输出:
Here's an elaboration of Kevin's answer. It's important to know that the expression to be returned is evaluated before
finally
, even if it is returned after.Output:
我尝试了上面的例子,稍加修改 -
上面的代码输出:
这是因为当执行
return i;
时,i
的值为 2。此后执行finally
块,其中 12 被分配给 < code>i 然后执行System.out
out。执行
finally
块后,try
块返回2,而不是返回12,因为该return 语句不会再次执行。如果您在 Eclipse 中调试这段代码,那么您会感觉到,在执行
finally
的System.out
后,会阻塞return
语句。 code>try 块再次执行。 但这种情况并非如此。 它只是返回值 2。I tried the above example with slight modification-
The above code outputs:
This is because when
return i;
is executedi
has a value 2. After this thefinally
block is executed where 12 is assigned toi
and thenSystem.out
out is executed.After executing the
finally
block thetry
block returns 2, rather than returning 12, because this return statement is not executed again.If you will debug this code in Eclipse then you'll get a feeling that after executing
System.out
offinally
block thereturn
statement oftry
block is executed again. But this is not the case. It simply returns the value 2.除了其他响应之外,重要的是要指出“finally”有权通过 try..catch 块覆盖任何异常/返回值。 例如,以下代码返回 12:
类似地,以下方法不会引发异常:
而以下方法会引发异常:
In addition to the other responses, it is important to point out that 'finally' has the right to override any exception/returned value by the try..catch block. For example, the following code returns 12:
Similarly, the following method does not throw an exception:
While the following method does throw it:
示例代码:
输出:
Example code:
Output:
另外,尽管这是不好的做法,但如果 finally 块中有 return 语句,它将胜过常规块中的任何其他返回。 也就是说,以下块将返回 false:
与从 finally 块抛出异常相同。
Also, although it's bad practice, if there is a return statement within the finally block, it will trump any other return from the regular block. That is, the following block would return false:
Same thing with throwing exceptions from the finally block.
以下是 Java 语言规范的官方措辞。
14.20.2。 try-finally 和 try-catch-finally 的执行
return
的规范实际上明确了这一点:JLS 14.17 退货声明
Here's the official words from the Java Language Specification.
14.20.2. Execution of try-finally and try-catch-finally
The specification for
return
actually makes this explicit:JLS 14.17 The return Statement
最后总是运行,这就是重点,仅仅因为它出现在返回之后的代码中并不意味着这就是它的实现方式。 Java 运行时有责任在退出
try
块时运行此代码。例如,如果您有以下内容:
运行时将生成如下内容:
如果抛出未捕获的异常,
finally
块将运行并且异常将继续传播。Finally is always run that's the whole point, just because it appears in the code after the return doesn't mean that that's how it's implemented. The Java runtime has the responsibility to run this code when exiting the
try
block.For example if you have the following:
The runtime will generate something like this:
If an uncaught exception is thrown the
finally
block will run and the exception will continue propagating.因为除非你调用 System.exit() (或者线程崩溃),否则finally 块将始终被调用。
Because a finally block will always be called unless you call
System.exit()
(or the thread crashes).简而言之,在官方 Java 文档(点击此处)中,写道——
Concisely, in the official Java Documentation (Click here), it is written that -
这是因为您将 i 的值指定为 12,但没有将 i 的值返回给函数。 正确的代码如下:
This is because you assigned the value of i as 12, but did not return the value of i to the function. The correct code is as follows:
是的,它会被调用。 这就是finally 关键字的全部意义所在。 如果跳出 try/catch 块可以跳过 finally 块,则与将 System.out.println 放在 try/catch 之外是一样的。
Yes it will get called. That's the whole point of having a finally keyword. If jumping out of the try/catch block could just skip the finally block it was the same as putting the System.out.println outside the try/catch.
并不总是
Java 语言规范描述了
try
-catch
-finally
和try
-catch
的方式code> 块在 14.20 工作.2它没有在任何地方指定始终执行
finally
块。但对于
try
-catch
-finally
和try
-finally
的所有情况> 块完成它确实指定在完成之前必须执行finally
。JLS 不保证FIN 在CODE 之后执行。
JLS 保证如果执行CODE 和NEXT,则FIN 将始终在CODE 之后和之前执行。 >下一步。
为什么 JLS 不保证
finally
块始终在try
块之后执行? 因为这是不可能的。 JVM 在完成try
块之后但在执行之前,不太可能但有可能中止(终止、崩溃、断电)。 code>finally
块。 JLS 无法采取任何措施来避免这种情况。因此,任何依赖于总是在
try
块完成后执行的finally
块来正常运行的软件都会被窃听。try
块中的return
指令与此问题无关。 如果执行到try
-catch
-finally
之后的代码,则保证finally
块将被执行之前,在try
块内有或没有return
指令。NOT ALWAYS
The Java Language specification describes how
try
-catch
-finally
andtry
-catch
blocks work at 14.20.2In no place it specifies that the
finally
block is always executed.But for all cases in which the
try
-catch
-finally
andtry
-finally
blocks complete it does specify that before completionfinally
must be executed.The JLS does not guarantee that FIN is executed after CODE.
The JLS guarantees that if CODE and NEXT are executed then FIN will always be executed after CODE and before NEXT.
Why doesn't the JLS guarantee that the
finally
block is always executed after thetry
block? Because it is impossible. It is unlikely but possible that the JVM will be aborted (kill, crash, power off) just after completing thetry
block but before execution of thefinally
block. There is nothing the JLS can do to avoid this.Thus, any software which for their proper behaviour depends on
finally
blocks always being executed after theirtry
blocks complete are bugged.return
instructions in thetry
block are irrelevant to this issue. If execution reaches code after thetry
-catch
-finally
it is guaranteed that thefinally
block will have been executed before, with or withoutreturn
instructions inside thetry
block.finally
块始终在返回x
的(计算出的)值之前执行。输出:
finally
block is always executed and before returningx
's (calculated) value.Output:
输入:
输出:
INPUT:
OUTPUT:
是的,它会。 无论 try 或 catch 块中发生什么,除非调用 System.exit() 或 JVM 崩溃。 如果块中有任何 return 语句,finally 将在该 return 语句之前执行。
Yes, it will. No matter what happens in your try or catch block unless otherwise System.exit() called or JVM crashed. if there is any return statement in the block(s),finally will be executed prior to that return statement.
是的,它会。
唯一不会出现的情况是 JVM 退出或崩溃
Yes It will.
Only case it will not is JVM exits or crashes
添加到 @vibhash 的答案,因为没有其他答案解释了在像下面这样的可变对象的情况下会发生什么。
会输出
Adding to @vibhash's answer as no other answer explains what happens in the case of a mutable object like the one below.
Will output
是的,finally 块总是被执行。 大多数开发人员使用此块来关闭数据库连接、结果集对象、语句对象,并且还使用 java hibernate 来回滚事务。
Yes, finally block is always execute. Most of developer use this block the closing the database connection, resultset object, statement object and also uses into the java hibernate to rollback the transaction.
我对不同论坛上提供的所有答案感到非常困惑,并决定最终编码并查看。 输出是:
即使 try 和 catch 块中有 return,finally 也会被执行。
输出
I was very confused with all the answers provided on different forums and decided to finally code and see. The ouput is :
finally will be executed even if there is return in try and catch block.
Output
System.exit(0)
in try and catch block in above code and an exception occurs before it,for any reason.finally
将会执行,这是肯定的。finally
在以下情况下不会执行:情况 1:
当您执行
System.exit()
时。情况 2:
当您的 JVM/线程崩溃时。
情况 3:
当您手动停止执行时。
finally
will execute and that is for sure.finally
will not execute in below cases:case 1 :
When you are executing
System.exit()
.case 2 :
When your JVM / Thread crashes.
case 3 :
When your execution is stopped in between manually.
我试过这个,
它是单线程的。
main
Thread
将永远处于wait
状态,因此finally
永远不会被调用,因此控制台输出不会
print
String
:在wait()
或finally
同意@Stephen C,上面的例子是这里提到的第三种情况之一:
在以下代码中添加更多这样的无限循环可能性:
情况2:如果 JVM 首先崩溃
参考:如何使 JVM 崩溃?
案例 6:如果
最后
block 将由守护进程Thread
执行,所有其他非守护进程Threads
在调用finally
之前退出。输出:这不会打印“finally”,这意味着“守护线程”中的“Finally block”没有执行
I tried this,
It is single threaded.
The
main
Thread
will be onwait
state forever, hencefinally
will never be called,so console output will not
print
String
: afterwait()
orfinally
Agreed with @Stephen C, the above example is one of the 3rd case mention here:
Adding some more such infinite loop possibilities in following code:
Case 2: If the JVM crashes first
Ref: How do you crash a JVM?
Case 6: If
finally
block is going to be executed by daemonThread
and all other non-daemonThreads
exit beforefinally
is called.output: This does not print "finally" which implies "Finally block" in "daemon thread" did not execute
考虑以下程序:
从 Java 1.8.162 开始,上述代码块给出以下输出:
这意味着使用
finally
来释放对象是一个很好的做法,如下代码所示:Consider the following program:
As of Java 1.8.162, the above code block gives the following output:
this means that using
finally
to free up objects is a good practice like the following code:这实际上在任何语言中都是如此......finally 总是在 return 语句之前执行,无论 return 位于方法体中的哪个位置。 如果不是这样,finally 块就没有多大意义。
That's actually true in any language...finally will always execute before a return statement, no matter where that return is in the method body. If that wasn't the case, the finally block wouldn't have much meaning.