终于总是在Java中执行?
我有一个try / catch块,里面有回报。 这个finally块会被调用吗?
例如:
try { something(); return success; } catch (Exception e) { return failure; } finally { System.out.println("i don't know if this will get printed out."); }
我知道我只需要input这个,看看会发生什么(实际上这就是我要做的事情),但是当我search到答案时,什么都没有出现,所以我想我会把这个问题放在一个问题上。
是的, finally
会被召唤。
finally
唯一不会被叫的是:
- 如果你调用
System.exit()
; - 如果JVM先崩溃了,
- 如果在
try
块中有一个无限循环(或其他一些不可中断的非终止语句) - 如果操作系统强制终止JVM进程, 例如UNIX上的“kill -9”。
- 如果主机系统死亡; 例如电源故障,硬件错误,操作系统恐慌等等。
certificate代码:
public static void main(String[] args) { System.out.println(Test.test()); } public static int test() { try { return 0; } finally { System.out.println("finally trumps return."); } }
输出:
finally trumps return. 0
另外,虽然这是不好的做法,但是如果在finally块中有一个return语句,它将会胜过来自常规块的任何其他返回。 也就是说,下面的块会返回false:
try { return true; } finally { return false; }
同样的事情,从finally块中抛出exception。
这里是Java语言规范的官方文字。
14.20.2。 try-finally和try-catch-finally的执行
带有
finally
块的try
语句通过首先执行try
块来执行。 那么有一个select:
- 如果
try
块的执行正常完成,- 如果
try
块的执行由于throw
一个值V而突然完成,- 如果
try
块的执行由于其他原因R而突然完成,则执行finally
块。 那么有一个select:
- 如果finally块正常完成,则由于原因R ,
try
语句突然完成。- 如果
finally
块由于S原因而突然完成,则对于原因S ,try
语句突然完成( 并且原因R被丢弃 )。
return
规范实际上使得这个明确:
JLS 14.17退货声明
ReturnStatement: return Expression(opt) ;
没有
Expression
return
语句尝试将控制权转移给包含它的方法或构造函数的调用者。带有
Expression
return
语句试图将控制转移到包含它的方法的调用者;Expression
的值将成为方法调用的值。前面的描述说“ 试图传输控制 ”而不是“ 传输控制 ”,因为如果在
try
或try
块包含return
语句的方法或构造函数中有任何try
语句,那么这些try
语句的任何finally
子句将被执行,在控制转移到方法或构造函数的调用者之前,从最内层到最外层。finally
一个子句的突然完成可能会中断由return
语句启动的控制权转移。
除了其他的回应之外,还有一点很重要,那就是'finally'有权通过try..catch块来覆盖任何exception/返回值。 例如,下面的代码返回12:
public static int getMonthsInYear() { try { return 10; } finally { return 12; } }
同样,下面的方法不会抛出exception:
public static int getMonthsInYear() { try { throw new RuntimeException(); } finally { return 12; } }
虽然下面的方法抛出它:
public static int getMonthsInYear() { try { return 12; } finally { throw new RuntimeException(); } }
我稍微修改了上面的例子,
public static void main(final String[] args) { System.out.println(test()); } public static int test() { int i = 0; try { i = 2; return i; } finally { i = 12; System.out.println("finally trumps return."); } }
上面的代码输出:
终于胜过回报。
2
这是因为当return i;
被执行, i
有一个值2.之后, finally
块被执行,其中12被分配给i
,然后System.out
出执行。
在执行finally
块之后, try
块返回2,而不是返回12,因为这个return语句不会被再次执行。
如果你将在Eclipse中debugging这个代码,那么你会得到一个感觉,执行完System.out
之后, try
块的return
语句再次被执行。 但事实并非如此。 它只是返回值2。
这是凯文的答案的详细说明。 知道要返回的expression式在finally
才被评估是重要的,即使是在返回之后。
public static void main(String[] args) { System.out.println(Test.test()); } public static int printX() { System.out.println("X"); return 0; } public static int test() { try { return printX(); } finally { System.out.println("finally trumps return... sort of"); } }
输出:
X finally trumps return... sort of 0
这是一个终极块的整个想法。 它可以让你确保你做清理,否则可能会被跳过,因为你当然返回,除其他事项。
最后被调用, 不pipe在try块中发生了什么 ( 除非你调用System.exit(int)
或Java虚拟机出于其他原因)。
思考这个问题的逻辑方法是:
- 放在finally块中的代码必须在try块内执行
- 因此,如果try块中的代码试图返回一个值或抛出一个exception,这个项目被放置在“货架上”,直到finally块可以执行
- 因为finally块中的代码(按定义)具有高优先级,所以它可以返回或抛出任何喜欢的东西。 在这种情况下,任何遗留在货架上的东西都会被丢弃。
- 唯一的例外是如果VM在try块中完全closures,例如通过“System.exit”
在最后的回报也会抛弃任何exception。 http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
最后总是执行,除非有exception程序终止(如调用System.exit(0)..)。 所以,你的系统将被打印
不,并不总是一个例外情况是// System.exit(0); 在finally块阻止之前终于执行。
class A { public static void main(String args[]) { DataInputStream cin = new DataInputStream(System.in); try{ int i=Integer.parseInt(cin.readLine()); }catch(ArithmeticException e){ }catch(Exception e){ System.exit(0);//Program terminates before executing finally block }finally(){ System.out.println("No error"); } }
}
因为除非调用System.exit()
(或线程崩溃),否则总是会调用finally块。
最后总是运行这是整个点,只是因为它出现在代码后,并不意味着这是如何实现的。 Java运行时有责任在退出try
块时运行这段代码。
例如,如果您有以下情况:
int foo() { try { return 42; } finally { System.out.println("done"); } }
运行时会产生这样的东西:
int foo() { int ret = 42; System.out.println("done"); return 42; }
如果抛出一个未捕获的exception, finally
块将会运行,exception将继续传播。
finally程序块总是被执行,除非由于JVM崩溃或System.exit(0)
的调用而导致程序终止exception。
最重要的是,从finally块中返回的任何值都会覆盖finally块执行之前返回的值,所以在最后使用try时要小心检查所有的出口点。
是的,它会被调用。 这是关键字的最后一个关键。 如果跳出try / catch块可以跳过finally块,就像把System.out.println放在try / catch之外一样。
简而言之,在官方的Java文档(点击这里 )中写道:
如果JVM在执行try或catch代码时退出,那么finally块可能不会执行。 同样,如果执行try或catch代码的线程被中断或终止,即使应用程序整体继续,finally块也可能不会执行。
是的,finally块总是执行。 大多数开发人员使用这个块closures数据库连接,resultset对象,语句对象,并且还使用java hibernate来回滚事务。
这在任何语言中都是真实的……最终将总是在return语句之前执行,而不pipe方法体中的哪个返回。 如果情况并非如此,那么最后的封锁就没有什么意义了。
因为在任何情况下总决赛都会被召唤。 你没有exception,它仍然被调用,捕获exception,它仍然被调用
考虑在正常的执行过程中(即没有抛出任何exception):如果方法不是“无效的”,那么它总是显式地返回一些东西,但最终总是得到执行
如果抛出exception,最后运行。 如果没有引发exception,最后运行。 如果发现exception,最后运行。 如果exception没有被捕获,最后运行。
只有当JVM退出时,它才会运行。
是的,它会。 不pipe你的try或catch块发生了什么,除非System.exit()调用或JVM崩溃。 如果块中有任何返回语句,最后将在该返回语句之前执行。
是的,它会。 只有情况下它不会是JVM退出或崩溃
finally块总是执行是否exception处理。如果在try块之前发生任何exception,finally块将不会执行。
这是因为您将i的值指定为12,但没有将i的值返回给函数。 正确的代码如下:
public static int test() { int i = 0; try { return i; } finally { i = 12; System.out.println("finally trumps return."); return i; } }
除了最后在try块中replacereturn的点之外,exception也是如此。 抛出exception的finally块会replacetry块中的返回或exception。
试试这个代码,你会明白finally代码块中的代码是在return语句后得到执行的 。
public class TestTryCatchFinally { static int x = 0; public static void main(String[] args){ System.out.println(f1() ); System.out.println(f2() ); } public static int f1(){ try{ x = 1; return x; }finally{ x = 2; } } public static int f2(){ return x; } }
最后总是阻止执行,不pipeexception对象是否发生。
终止阻止有两种可能:1. return语句。 2. System.exit(0);
public class test { public static void main(String[] args) { if(true) { return; } try { System.out.println(1); return;
思考这个问题的逻辑方法是:
放在finally块中的代码必须在try块内执行。
因此,如果try块中的代码试图返回一个值或抛出一个exception,这个项目被放置在“架子上”,直到finally块可以执行为止。因为finally块中的代码具有(根据定义)高优先级,它可以返回或抛出不pipe它喜欢什么 在这种情况下,任何遗留在货架上的东西都会被丢弃。
唯一的例外是如果VM在try块中完全closures,例如通过“System.exit”
永远不要从finally块中抛出任何exception
try { someMethod(); //Throws exceptionOne } finally { cleanUp(); //If finally also threw any exception the exceptionOne will be lost forever }
这很好,只要cleanUp()永远不会抛出任何exception。 在上面的例子中,如果someMethod()抛出一个exception,并且在finally块中,cleanUp()抛出一个exception,那么第二个exception将从方法中出来,原来的第一个exception(正确的原因)将永远丢失。 如果您在finally块中调用的代码可能会引发exception,请确保您要么处理它,要么将其logging下来。 永远不要让它从最后的块里出来。
实际上退出程序(通过调用System.exit()或通过导致导致进程中止的致命错误:有时在Windows中非正式地称为“热点”或“Dr.Watson”)将会阻止您的finally块被阻止执行!
没有什么可以阻止我们嵌套try / catch / finally块(例如,把一个try / catch块放在try / catch块内,反之亦然),这并不罕见。