1. ホーム
  2. java

Try-catch-finally-returnの明確化 [重複]について

2023-09-16 03:20:28

質問

上記のトピック(タイトル参照)に関連する、このフォーラムで既に行われたすべての質問を読むことで、私は以下を十分に理解しました。 finally は常に呼び出されることを理解しました。(ただし System.exit と無限ループを除く)。 しかし、私が知りたいのは、もし return がキャッチブロックの中で呼び出され、その後別の 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は常に実行されるということです。しかし、他の "return" は全く実行されないと思います。catch節のreturnですでに書き込まれている内容の上にfinallyが書き込まれるというのは、多くの投稿で見かけました。私の理解では、catch節の戻り値が評価されようとするとすぐに、制御フローは別の戻り値を持つfinally節に渡され、今度はcatch節に制御を戻さずに戻り値が評価されます。このようにして、唯一の return 実行時に呼ばれるのはfinally returnだけです。あなたはこれに同意しますか?

A returnfinally は、プログラムに制御を渡さず、値を返してメソッドを終了させます。そう言っていいのでしょうか?

どのように解決するのですか?

もし return の中に try ブロックに到達すると、制御を finally ブロックに制御を移し、関数は最終的に正常に戻ります(throwではありません)。

例外が発生しても、その後にコードが return から catch ブロックから、制御は finally ブロックに移行し、最終的に関数は正常に戻ります(throwではありません)。

あなたの例では 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

...このコードは fooArrayIndexOutOfBoundsException . しかし finally ブロックは return を実行すると、その例外は抑制されます。

このような理由から、この記事では returnfinally .