52

このコードを考えると:

String test() {
    try {
        return "1";
    } finally {
        return "2";
    }
}

言語仕様は への呼び出しの戻り値を定義していtest()ますか? 言い換えれば、すべての JVM で常に同じですか?

Sun JVM では戻り値は ですが2、これは VM に依存しないことを確認したいと思います。

4

7 に答える 7

58

はい、言語仕様では、「2」が結果であると定義されています。VM が別の方法で行う場合、それは仕様に準拠していません。

ほとんどのコンパイラはそれについて不平を言うでしょう。たとえば、Eclipse は、return ブロックは決して実行されないと主張しますが、それは誤りです。

そのようなコードを書くのは驚くほど悪い習慣です。絶対にやらないでください:)

于 2010-02-22T09:38:48.413 に答える
20

はい、Java 言語仕様はこの問題について非常に明確です ( 14.20.2 ):

finally ブロックを含む try ステートメントは、最初に try ブロックを実行することによって実行されます。次に、選択肢があります。

  • try ブロックの実行が正常に完了すると [...]
  • 値 V のスローにより、try ブロックの実行が突然完了した場合 [...]
  • try ブロックの実行が R 以外の理由で突然終了した場合、finally ブロックが実行されます。次に、選択肢があります。
    • finally ブロックが正常に終了した場合 [...]
    • finally ブロックが理由 S で突然終了した場合、try ステートメントは理由 S で突然終了します (理由 R は破棄されます)。
于 2010-02-22T10:25:20.427 に答える
19

次の例を除いて、finally ブロックは常に実行されます。

String test() {
    try {
        System.exit(0);
    } finally {
        return "2";
    }
}

この場合、JVM はfinallyブロックを実行せずに停止します。

したがって、あなたの例では、戻り値は になります2

于 2010-02-22T09:42:04.553 に答える
7

はい、ブロックから何かを返すと、 orブロックfinallyから返された可能性のあるものはすべて置き換えられます。trycatch

例外についても同様です。ブロックで何かをスローするとfinally、その例外は、tryまたはcatchブロックでスローされた例外を置き換えます。finallyしたがって、失敗の元の理由が隠される可能性があるため、ブロックに何かをスローしないように注意してください。

于 2010-02-22T09:52:07.840 に答える
4

プログラムの ByteCode を読み取ると、コードは次のようになります。

finally ブロック ステートメントは try ブロックの return ステートメントの前にインライン化されるため、finally ブロックからの return が最初に実行され、元の return ステートメントは決して実行されません。

プログラムの場合:

String test() {
        try {
            System.out.println("try");
            return "1";
        } finally {
            System.out.println("finally");
            return "2";
        }
    }

次のように変換されます。

String test()
    {
        System.out.println("try");
        String s = "1"; //temporary variable 
        System.out.println("finally");
        return "2";
        Exception exception;
        exception;
        System.out.println("finally");
        return "2";
    }

プログラムの場合: catchブロックを使用:

String test() {

        try {
            System.out.println("try");
            return "1";
        } catch (RuntimeException e) {
            System.out.println("catch");
            return "2";
        } finally {
            System.out.println("finally");
            return "3";
        }
    }

に変換:

String test()
    {
        System.out.println("try");
        String s = "1";
        System.out.println("finally");
        return "3";
        RuntimeException e;
        e;
        System.out.println("catch");
        String s1 = "2";
        System.out.println("finally");
        return "3";
        Exception exception;
        exception;
        System.out.println("finally");
        return "3";
    }

注: JDK 1.7 を使用してコンパイルし、Cavaj を使用して逆コンパイルしました。

于 2015-07-28T10:27:05.027 に答える
1

以下のリンクを参照できます。すべての詳細が提供されることを願っています:

http://www.programmerinterview.com/index.php/java-questions/will-finally-run-after-return/

tryまたはcatchブロックにreturnステートメントがあっても、finallyブロックは常に実行されると言われています。また、finally ブロックにも return ステートメントがある場合、これは try または catch ブロック内にある return ステートメントをオーバーライドし、この場合、try/catch でスローされた例外はすべて破棄されます (悪いアプローチ)。

于 2015-03-26T14:25:34.040 に答える
0

上記の回答は非常によくまとめられていますが、ここでもう 1 点追加します。

private static int divide(int a , int b){
    try{
        return  a/b;
    }finally{
        System.out.println("In finally");
        return 1;
    }
}

1,0 を渡すと、上記のメソッドはスローされた例外を抑制し、結果のみを返します。上記のコードは本番環境では使用しないでください。

  private static int divide(int a , int b){
        int result = 0;
        try{
            result =   a/b;
        }finally{
            System.out.println("In finally");
            result =  1;
        }

        return result;
    }

finally ブロックの後に return ステートメントを使用すると、

Exception in thread "main" java.lang.ArithmeticException: / by zero
于 2019-01-14T18:44:16.853 に答える