1. ホーム
  2. java

[解決済み] finally ブロックで戻り値の変数を変更しても、戻り値が変更されないのはなぜですか?

2022-05-09 18:39:32

質問

以下のような簡単なJavaクラスがあります。

public class Test {

    private String s;

    public String foo() {
        try {
            s = "dev";
            return s;
        } 
        finally {
            s = "override variable s";
            System.out.println("Entry in finally Block");  
        }
    }

    public static void main(String[] xyz) {
        Test obj = new Test();
        System.out.println(obj.foo());
    }
}

そして、このコードの出力はこうです。

Entry in finally Block
dev  

なぜ s はオーバーライドされません。 finally ブロックの中で、印刷出力を制御していますか?

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

その try の実行でブロックは完了します。 return ステートメントと s を実行した時点で return ステートメントが実行されると、そのメソッドから返される値になります。という事実は finally の値を後で変更します。 s (の後)。 return 文が完了しても、(その時点では)戻り値は変わりません。

の値の変更に対処していることに注意してください。 s の中にある finally ブロックではなく、そのオブジェクトに s を参照しています。もし s はミュータブルオブジェクトへの参照であった(これは String はそうではない)、そして 内容 のオブジェクトが変更されました。 finally というブロックがあれば、その変更は戻り値に反映される。

このような動作の詳細なルールは、以下のページにあります。 Java言語仕様書14.20.2項 . を実行することに注意してください。 return 文の突然の終了としてカウントされます。 try ブロック(".で始まる部分。 その他の理由でtryブロックの実行が突然終了した場合 R.... "が適用されます)。参照 JLS 14.17項 を使用する理由については return 文は、ブロックの突然の終了を意味します。

さらに詳しく説明すると、もし try ブロックと finally ブロック の try-finally ステートメントが突然終了するのは return ステートメントを使用する場合、§14.20.2の以下のルールが適用されます。

を実行した場合 try ブロックが例外を発生させる以外の何らかの理由で突然終了した場合、その後に finally ブロックが実行され、その後、選択肢がある。

  • もし finally ブロックが正常に終了すると try 文は理由Rで突然終了する。
  • もし finally ブロックが理由Sで突然終了した場合は try 文は理由 S で突然終了する (そして理由 R は破棄される)。

その結果 return の文は finally ブロック全体の戻り値を決定します。 try-finally ステートメントから返される値であり try ブロックは破棄されます。同様のことが try-catch-finally 文は、もし try ブロックが例外を投げると、それをキャッチするのは catch ブロックの両方が catch ブロックと finally ブロックには return ステートメントを使用します。