Try-catch-finally-return 澄清

通过阅读所有的问题已经在这个论坛有关的主题(见标题) ,我完全理解 finally总是被调用。(除了 System.exit和无限循环)。但是,我想知道是否在 catch 块中调用了 return,然后在 finally 块中调用了另一个 return

例如:

public static void main(String[]args) {
int a = new TestClass().absorbeTheValue();
}


int absorbeTheValue() {
try {
int a = 10/0;
if (a > 0) return 4;
} catch(Exception e) {
return 45;
} finally {
return 34;
}
}

所以这里的输出(当方法被调用时)在任何情况下都是34。这意味着最终总是会被运行。我认为,虽然其他“回报”不运行在所有。在许多帖子中,我发现最终写的内容是在 catch 子句 return 已经写过的内容之上。我的理解是,一旦 catch 子句中的返回值即将被计算,控制流就会传递给 finally 子句,而 finally 子句又会传递另一个返回值,这一次,返回值将被计算,而不会将控制传递回 catch 子句。这样,在运行时调用的唯一 return将是 finally 返回。你同意吗?

finally中的 return不会将控件传递回程序,而是返回值并终止方法。可以这么说吗?

130497 次浏览

如果到达 try块中的 return,它将控制权转移到 finally块,函数最终将正常返回(而不是抛出)。

如果发生异常,但是代码从 catch块到达 return,控制被转移到 finally块,函数最终正常返回(而不是抛出)。

在您的示例中,在 finally中有一个 return,因此无论发生什么,函数都将返回 34,因为 finally有最后一个单词(如果您愿意的话)。

虽然在您的示例中没有涉及到,但是即使您没有 catch,并且在 try块中抛出了异常且 没有被捕获,这也是正确的。通过从 finally块执行 return,可以完全抑制异常。考虑一下:

public class FinallyReturn {
public static final void main(String[] args) {
System.out.println(foo(args));
}


private static int foo(String[] args) {
try {
int n = Integer.parseInt(args[0]);
return n;
}
finally {
return 42;
}
}
}

如果不提供任何参数就运行它:

$ java FinallyReturn

...the code in foo throws an ArrayIndexOutOfBoundsException. But because the finally block does a return, that exception gets suppressed.

This is one reason why it's best to avoid using return in finally.

下面是一些代码,展示了它是如何工作的。

class Test
{
public static void main(String args[])
{
System.out.println(Test.test());
}


public static String test()
{
try {
System.out.println("try");
throw new Exception();
} catch(Exception e) {
System.out.println("catch");
return "return";
} finally {
System.out.println("finally");
return "return in finally";
}
}
}

结果是:

try
catch
finally
return in finally