74

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

例如:

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。这意味着 finally 总是运行。我认为虽然其他“回报”根本没有运行。在许多帖子中,我发现最终将内容写入 catch 子句返回已经写入的内容。我的理解是,一旦 catch 子句中的返回值即将被评估,控制流就会传递给 finally 子句,该子句又会返回另一个返回值,这一次将评估返回值,而不会将控制权传递回 catch 子句. 这样,return在运行时唯一调用的将是 finally 返回。你同意吗?

A returninfinally不会将控制权传递回程序,而是返回值并终止方法。我们可以这么说吗?

4

2 回答 2

114

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

如果发生异常,但随后代码returncatch块中到达 a,则控制权将转移到finally块,并且函数最终正常返回(而不是 throw)。

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

尽管您的示例中没有涉及,但即使您没有,并且如果在块catch中引发异常并且捕获异常,这也是正确的。通过从块中执行,您可以完全抑制异常。考虑:tryreturnfinally

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 最终返回

...中的代码foo抛出一个ArrayIndexOutOfBoundsException. 但是因为该finally块做了 a return,所以该异常被抑制了。

这是最好避免使用returnin的原因之一finally

于 2013-03-05T14:11:24.040 回答
84

这是一些显示它如何工作的代码。

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
于 2013-03-05T14:18:20.370 回答