尝试捕获 - 最终返回澄清

时间:2013-03-05 14:05:48

标签: java return try-catch finally

通过阅读本论坛中已经提到的与上述主题相关的所有问题(见标题),我完全理解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子句返回已写入的内容。我的理解是,一旦catch子句中的返回值即将被评估,控制流就会传递给finally子句,而子句又有另一个返回,这次返回将被评估,而不会将控制权传递给catch子句。通过这种方式,在运行时调用的唯一return将是最终返回。你同意吗?

return中的finally不会将控件传回程序,但会返回该值并终止该方法。我们可以这样说吗?

2 个答案:

答案 0 :(得分:93)

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

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

在您的示例中,return中有finally,因此无论发生什么情况,该函数都会返回34,因为finally具有最终结果(如果你愿意的话。

虽然您的示例中未涉及,但即使您没有catch并且try块中存在异常并且,也会如此抓住。通过从return块执行finally,您可以完全禁止该异常。考虑:

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

... foo中的代码会引发ArrayIndexOutOfBoundsException。但由于finally块执行return,该异常会被抑制。

这就是为什么最好避免在return中使用finally的原因之一。

答案 1 :(得分:67)

以下是一些显示其工作原理的代码。

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