终于总是在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唯一不会被叫的是:

  1. 如果你调用System.exit() ;
  2. 如果JVM先崩溃了,
  3. 如果在try块中有一个无限循环(或其他一些不可中断的非终止语句)
  4. 如果操作系统强制终止JVM进程, 例如UNIX上的“kill -9”。
  5. 如果主机系统死亡; 例如电源故障,硬件错误,操作系统恐慌等等。

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块正常完成,则由于原因Rtry语句突然完成。
    • 如果finally块由于S原因而突然完成,则对于原因Stry语句突然完成( 并且原因R被丢弃 )。

return规范实际上使得这个明确:

JLS 14.17退货声明

 ReturnStatement: return Expression(opt) ; 

没有Expression return语句尝试将控制权转移给包含它的方法或构造函数的调用者。

带有Expression return语句试图将控制转移到包含它的方法的调用者; Expression的值将成为方法调用的值。

前面的描述说“ 试图传输控制 ”而不是“ 传输控制 ”,因为如果在trytry块包含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虚拟机出于其他原因)。

思考这个问题的逻辑方法是:

  1. 放在finally块中的代码必须在try块内执行
  2. 因此,如果try块中的代码试图返回一个值或抛出一个exception,这个项目被放置在“货架上”,直到finally块可以执行
  3. 因为finally块中的代码(按定义)具有高优先级,所以它可以返回或抛出任何喜欢的东西。 在这种情况下,任何遗留在货架上的东西都会被丢弃。
  4. 唯一的例外是如果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块内,反之亦然),这并不罕见。