java - 始终在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.");
}

我知道我可以,只要输入这个一个看看会发生什么( 这就是我将要做的,实际上) 但是当我在谷歌上搜索寻找答案,没反映了,所以我觉得还是抛出这里资源作为问题。

时间:

finally 将被调用。

finally 不会被调用的唯一次数是:

  1. 如果你调用 System.exit() 或者
  2. 另一个线程中断当前的或者
  3. 如果JVM首先崩溃

//proof 代码


class Test
{
 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语句,它将从常规块中返回任何其他返回。 也就是说,以下块将 return false:


try { return true; } finally { return false; }

从finally块抛出异常的相同事情。

下面是来自Java语言规范的官方词汇。

JLS 14.20.2 try-catch-finally的执行

用一个 finally 程序块分别由一个 try 语句即先执行 try 块。 然后有一个选择:

  • 如果 try 块的执行正常完成,则 [... ]
  • 如果 V try 块的执行完成后突然因一 throw的一个值,[... ]
  • 如果 try 块的执行完成后突然由于任何其他原因 R,那么 finally 块被执行。 然后有一个选择:
    • 如果finally块正常完成,那么 try 语句会突然完成,原因是 R 。
    • 如果 finally 块完成后突然 S,那么原因,这里为原因语句完成 try 突然的 ( 和原因 R 被丢弃) 。

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

JLS 14.17返回语句


ReturnStatement:
 return Expression(opt) ;

return 声明没有 Expression 试图转移控制方法或者构造函数的调用程序包含它。

return 语句和一个 Expression 试图转移控制方法包含它的调用程序; Expression的值变成了方法调用的值。

前面的描述说" 试图转移控制"而不是"传送控制"因为如果有任何在方法或者构造函数的trytry 语句块包含 return 语句,那么任何 finallytry 语句将执行的条款,在秩序,最外层,在控制转移到方法或者构造函数的调用者。 finally 子句突然完成会中断 return 语句启动的控制转移。

除了其他响应之外,重要的是指出'最后'有权通过 try catch block块覆盖任何异常/返回值。 例如以下代码返回 12:


public static int getMonthsInYear(){
 try{
 return 10;
 } finally {
 return 12;
 }
}

类似地,以下方法不会引发异常:


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,因为返回语句不会再次执行。

如果你将这段代码调试 Eclipse 之后你会得到一个感觉,执行 System.outfinallytryreturn 语句块执行一次。 但这不是事实。 它只返回值 2.

这就是finally块的整体概念。 它让你能确认执行清理操作较有可能被跳过,因为你返回,以及其他一些信息,当然。

于一些其他reason,相关死亡最终称为无论会发生什么在try块中,除非 你在Java虚拟机调用 System.exit(int) 或者刺激的出去。

这里有个精致的凯文 的回答。 重要的是要知道要返回的表达式在 finally 之前求值,即使在。


class Test
{
 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

...