このコードを考えると:
String test() {
try {
return "1";
} finally {
return "2";
}
}
言語仕様は への呼び出しの戻り値を定義していtest()
ますか? 言い換えれば、すべての JVM で常に同じですか?
Sun JVM では戻り値は ですが2
、これは VM に依存しないことを確認したいと思います。
はい、言語仕様では、「2」が結果であると定義されています。VM が別の方法で行う場合、それは仕様に準拠していません。
ほとんどのコンパイラはそれについて不平を言うでしょう。たとえば、Eclipse は、return ブロックは決して実行されないと主張しますが、それは誤りです。
そのようなコードを書くのは驚くほど悪い習慣です。絶対にやらないでください:)
はい、Java 言語仕様はこの問題について非常に明確です ( 14.20.2 ):
finally ブロックを含む try ステートメントは、最初に try ブロックを実行することによって実行されます。次に、選択肢があります。
- try ブロックの実行が正常に完了すると [...]
- 値 V のスローにより、try ブロックの実行が突然完了した場合 [...]
- try ブロックの実行が R 以外の理由で突然終了した場合、finally ブロックが実行されます。次に、選択肢があります。
- finally ブロックが正常に終了した場合 [...]
- finally ブロックが理由 S で突然終了した場合、try ステートメントは理由 S で突然終了します (理由 R は破棄されます)。
次の例を除いて、finally ブロックは常に実行されます。
String test() {
try {
System.exit(0);
} finally {
return "2";
}
}
この場合、JVM はfinally
ブロックを実行せずに停止します。
したがって、あなたの例では、戻り値は になります2
。
はい、ブロックから何かを返すと、 orブロックfinally
から返された可能性のあるものはすべて置き換えられます。try
catch
例外についても同様です。ブロックで何かをスローするとfinally
、その例外は、try
またはcatch
ブロックでスローされた例外を置き換えます。finally
したがって、失敗の元の理由が隠される可能性があるため、ブロックに何かをスローしないように注意してください。
プログラムの 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 を使用して逆コンパイルしました。
以下のリンクを参照できます。すべての詳細が提供されることを願っています:
http://www.programmerinterview.com/index.php/java-questions/will-finally-run-after-return/
tryまたはcatchブロックにreturnステートメントがあっても、finallyブロックは常に実行されると言われています。また、finally ブロックにも return ステートメントがある場合、これは try または catch ブロック内にある return ステートメントをオーバーライドし、この場合、try/catch でスローされた例外はすべて破棄されます (悪いアプローチ)。
上記の回答は非常によくまとめられていますが、ここでもう 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