上記のトピックに関連するこのフォーラムで既に尋ねられたすべての質問(タイトルを参照)を読むことにより、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
のみが最終的に戻ります。それに同意しますか?
return
のfinally
は、コントロールをプログラムに戻しませんが、値を返し、メソッドを終了します。そう言えますか?
return
ブロック内のtry
に到達すると、finally
ブロックに制御が移り、関数は最終的に(スローではなく)戻ります。
例外が発生したが、コードがreturn
ブロックからcatch
に到達した場合、制御はfinally
ブロックに転送され、関数は最終的に(スローではなく)戻ります。
あなたの例では、return
にfinally
があります。したがって、何が起こるかに関係なく、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
を実行するため、その例外は抑制されます。
これが、return
でfinally
を使用しないことが最善の理由の1つです。
これがどのように機能するかを示すコードを次に示します。
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