尝试-捕获-最终-返回澄清

2022-08-31 12:58:14

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

例如:

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 子句。这样,在运行时调用的唯一操作将是最终返回。你同意这种说法吗?return

A 不会将控件传递回程序,但返回值并终止该方法。我们能这样说吗?returnfinally


答案 1

如果到达块中的 ,它将控制权转移到块,并且函数最终正常返回(而不是 throw)。returntryfinally

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

在你的示例中,你在 中具有 a,因此无论发生什么情况,该函数都将返回 ,因为具有最后一个(如果您愿意的话)单词。returnfinally34finally

尽管您的示例中未涵盖,但即使您没有,并且如果在块中抛出异常并且未捕获,也是如此。通过从块执行 a,可以完全禁止显示异常。考虑:catchtryreturnfinally

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

...中的代码会抛出一个 .但是因为块执行 了 一个 ,所以该异常被抑制。fooArrayIndexOutOfBoundsExceptionfinallyreturn

这是最好避免在 中使用 的原因之一。returnfinally


答案 2

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

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