web-dev-qa-db-ja.com

try-catch-finally-returnの説明

上記のトピックに関連するこのフォーラムで既に尋ねられたすべての質問(タイトルを参照)を読むことにより、finallyが常に呼び出されることを完全に理解します。 (System.exitおよび無限ループを除く)。ただし、returnがcatchブロックで呼び出され、次に別の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になります。最終的に常に実行されることを意味します。他の「リターン」はまったく実行されないと思います。多くの投稿で、catch句のreturnによって既に書き込まれた内容にコンテンツを最終的に書き込むという事実を見つけました。私の理解では、catch句の戻り値が評価されようとするとすぐに、制御フローがfinally句に渡され、finally句に別の戻りがあり、今回はcatch句に制御を戻さずに戻りが評価されます。このようにして、実行時に呼び出されるreturnのみが最終的に戻ります。それに同意しますか?

returnfinallyは、コントロールをプログラムに戻しませんが、値を返し、メソッドを終了します。そう言えますか?

59
Rollerball

returnブロック内のtryに到達すると、finallyブロックに制御が移り、関数は最終的に(スローではなく)戻ります。

例外が発生したが、コードがreturnブロックからcatchに到達した場合、制御はfinallyブロックに転送され、関数は最終的に(スローではなく)戻ります。

あなたの例では、returnfinallyがあります。したがって、何が起こるかに関係なく、finallyには最終的なものがあるため、関数は34を返します。 ) 語。

例では説明していませんが、catchがなく、tryブロックで例外がスローされ、notキャッチされた場合でも、これは当てはまります。 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を実行するため、その例外は抑制されます。

これが、returnfinallyを使用しないことが最善の理由の1つです。

97
T.J. Crowder

これがどのように機能するかを示すコードを次に示します。

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
70
andre