このコードを考えると、絶対確実あれfinally
ブロックは何を実行しても常に実行されます。something()
は何ですか?
try {
something();
return success;
}
catch (Exception e) {
return failure;
}
finally {
System.out.println("i don't know if this will get printed out.");
}
はい、finally
tryまたはcatchコードブロックの実行後に呼び出されます。
唯一の回finally
呼ばれることはありません:
System.exit()
;try
またはcatch
ブロック;thread.stop()
必ずしも防ぐわけではないfinally
実行されないようにブロックします。 - Piotr Findeisenfinally
ブロックが呼び出されます後にのtry
ブロックし、前制御は以下のステートメントに渡されます。これは、無限ループを含むtryブロックと一致しているため、finallyブロックは実際には呼び出されません。 - Andrzej Doyle
コード例:
public static void main(String[] args) {
System.out.println(Test.test());
}
public static int test() {
try {
return 0;
}
finally {
System.out.println("finally trumps return.");
}
}
出力:
finally trumps return.
0
finally
〜とreturn 2;
許可されていません(Compiler-Error)。 - Alexander Pacha
また、これは悪い習慣ですが、finallyブロック内にreturn文があると、通常のブロックからの他の戻り値よりも優先されます。つまり、次のブロックはfalseを返します。
try { return true; } finally { return false; }
finallyブロックから例外をスローするのと同じことです。
これがJava言語仕様からの公式の言葉です。
14.20.2。 try-finallyおよびtry-catch-finallyの実行
A
try
のステートメントfinally
ブロックは最初にtry
ブロック。それから選択があります:
- の実行の場合
try
ブロックは正常に完了します、[...]- の実行の場合
try
ブロックが原因で突然完了するthrow
値のV、[...]- の実行の場合
try
ブロックは他の何らかの理由で突然完了しますR、 そうしてfinally
ブロックが実行されます。それから選択があります:
- finallyブロックが正常に完了すると、
try
文は理由で突然完了しますR。- あれば
finally
ブロックは理由のために突然完了しますS、 そうしてtry
文は理由で突然完了しますS(そして理由R破棄されます)
の仕様return
実際にこれを明示的にする:
ReturnStatement: return Expression(opt) ;
A
return
noのあるステートメントExpression
試みそれを含むメソッドまたはコンストラクタの呼び出し側に制御を移す。A
return
ステートメントExpression
試みそれを含むメソッドの呼び出し元に制御を移す。の値Expression
メソッド呼び出しの値になります。前述の説明は「試み制御を転送する「ただではなく」制御を転送する「あれば
try
メソッドまたはコンストラクタ内のステートメントtry
ブロックにはreturn
文、それからanyfinally
それらの節try
制御がメソッドまたはコンストラクターの呼び出し側に渡される前に、ステートメントは最も内側から外側の順序で実行されます。の突然の完了finally
条項によって開始された制御の移管が中断される可能性があります。return
ステートメント。
他の応答に加えて、 'finally'がtry..catchブロックによって例外/戻り値をオーバーライドする権利を持つことを指摘することは重要です。たとえば、次のコードは12を返します。
public static int getMonthsInYear() {
try {
return 10;
}
finally {
return 12;
}
}
同様に、次のメソッドは例外をスローしません。
public static int getMonthsInYear() {
try {
throw new RuntimeException();
}
finally {
return 12;
}
}
次のメソッドはそれをスローしますが:
public static int getMonthsInYear() {
try {
return 12;
}
finally {
throw new RuntimeException();
}
}
上記の例を少し修正してみました。
public static void main(final String[] args) {
System.out.println(test());
}
public static int test() {
int i = 0;
try {
i = 2;
return i;
} finally {
i = 12;
System.out.println("finally trumps return.");
}
}
上記のコードは次のように出力されます。
最後に切り札が戻ります。
2
これはreturn i;
実行されますi
値2があります。finally
12が割り当てられているブロックが実行されますi
その後System.out
outが実行されます。
実行後finally
ブロックするtry
このreturn文は再度実行されないため、blockは12を返すのではなく2を返します。
あなたがEclipseでこのコードをデバッグするならば、あなたは実行した後にそのように感じるでしょうSystem.out
のfinally
ブロックするreturn
の声明try
ブロックは再度実行されます。しかし、そうではありません。単に値2を返します。
i
プリミティブではなく、Integerオブジェクトです。 - Yamcha
これはの詳細ですケビンの答え。返される式が前に評価されることを知っておくことは重要ですfinally
後に返ってきても。
public static void main(String[] args) {
System.out.println(Test.test());
}
public static int printX() {
System.out.println("X");
return 0;
}
public static int test() {
try {
return printX();
}
finally {
System.out.println("finally trumps return... sort of");
}
}
出力:
X
finally trumps return... sort of
0
それがfinallyブロックの全体的な考え方です。それはあなたがあなたが他のものの間で、とりわけ戻るので、あなたがそうでなければスキップされるかもしれないクリーンアップをすることをあなたに確かにさせます。
最後に呼ばれる何があってもtryブロック内(ない限りあなたが呼ぶSystem.exit(int)
またはJava Virtual Machineが他の理由で起動します。
これについて考える論理的な方法は、次のとおりです。
また、やっと戻ってくると、例外がすべて捨てられます。http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
(System.exit(0)を呼び出すように)プログラムの異常終了がない限り、finallyは常に実行されます。だから、あなたのSYSOUTが表示されます
いいえ、必ずしも1つの例外が//というわけではありません System.exit(0); finallyブロックの前にfinallyが実行されるのを防ぎます。
class A {
public static void main(String args[]){
DataInputStream cin = new DataInputStream(System.in);
try{
int i=Integer.parseInt(cin.readLine());
}catch(ArithmeticException e){
}catch(Exception e){
System.exit(0);//Program terminates before executing finally block
}finally{
System.out.println("Won't be executed");
System.out.println("No error");
}
}
}
JVMがクラッシュしたこと、またはJVMの呼び出しによってプログラムが異常終了しない限り、finallyブロックは常に実行されます。System.exit(0)
。
それに加えて、finallyブロック内から返される値は、finallyブロックの実行前に返される値をオーバーライドするので、try finallyを使うときはすべての出口点をチェックするように注意してください。
それがリターンの後にコードに表示されるという理由だけで、最後に常に実行されるのがポイントです。それはそれが実装される方法であることを意味するものではありません。 Javaランタイムは、終了時にこのコードを実行する責任があります。try
ブロック。
たとえば、次のようになっているとします。
int foo() {
try {
return 42;
}
finally {
System.out.println("done");
}
}
ランタイムは次のようなものを生成します。
int foo() {
int ret = 42;
System.out.println("done");
return 42;
}
キャッチされていない例外がスローされた場合finally
ブロックが実行され、例外が伝播し続けます。
これは、iの値を12として代入したが、関数にiの値を返さなかったためです。正しいコードは次のとおりです。
public static int test() {
int i = 0;
try {
return i;
} finally {
i = 12;
System.out.println("finally trumps return.");
return i;
}
}
あなたが呼び出さない限り、finallyブロックは常に呼ばれるからです。System.exit()
(またはスレッドがクラッシュした)
簡潔に言えば、公式のJavaドキュメンテーション(クリックしてここに)、それが書かれている -
tryまたはcatchコードの実行中にJVMが終了すると、 finallyブロックは実行できません。同様に、実行中のスレッドが tryまたはcatchコードが中断または中止された場合、finallyブロックは アプリケーション全体が継続しても実行されません。
答えは簡単はい。
入力:
try{
int divideByZeroException = 5 / 0;
} catch (Exception e){
System.out.println("catch");
return; // also tried with break; in switch-case, got same output
} finally {
System.out.println("finally");
}
出力:
catch
finally
はい、それは呼ばれるでしょう。それがfinallyキーワードを持つことの全体的なポイントです。 try / catchブロックから飛び出してfinallyブロックを飛ばすことができれば、System.out.printlnをtry / catchの外側に置くのと同じことになります。
はい、できます。他の方法でSystem.exit()が呼び出されたりJVMがクラッシュしたりしない限り、tryまたはcatchブロックで何が起きても関係ありません。ブロック内にreturnステートメントがある場合は、そのreturnステートメントの前に最後に実行されます。
はいそうでしょう。 JVMが終了またはクラッシュしない場合のみ
はい、最後にブロックは常に実行されます。開発者のほとんどはこのブロックを使用してデータベース接続、結果セットオブジェクト、ステートメントオブジェクトをクローズし、さらにトランザクションをロールバックするためにJava Hibernateに使用します。
次のプログラムを考えてください。
public class someTest {
private static StringBuilder sb = new StringBuilder();
public static void main(String args[]) {
System.out.println(someString());
System.out.println("---AGAIN---");
System.out.println(someString());
}
private static String someString() {
try {
sb.append("-abc-");
return sb.toString();
} finally {
sb.append("xyz");
}
}
}
Java 1.8.162以降、上記のコードブロックは次のように出力されます。
-abc-
---AGAIN---
-abc-xyz-abc-
これは、finally
オブジェクトを解放することは、次のコードのように良い習慣です。
private static String someString() {
StringBuilder sb = new StringBuilder();
try {
sb.append("abc");
return sb.toString();
} finally {
sb = null;
}
}
sb.setLength(0)
最後に? - user7294900
それは実際にはどの言語でも当てはまります...その戻り値がメソッド本体のどこにあっても、最終的には常にreturnステートメントの前に実行されます。そうでなければ、finallyブロックはあまり意味がありません。
finally
そもそも… - glglgl
なぜならファイナルはあなたが持っているどんな場合でも常に呼ばれるからです。あなたは例外を持っていない、それはまだ呼ばれている、例外をキャッチ、それはまだ呼ばれている
通常の実行の過程でこれを考慮してください(すなわち、例外がスローされることはありません)。
例外が発生した場合は、最後に実行されます。例外がスローされない場合は、最後に実行されます。例外が発生した場合は、最後に実行されます。例外が捕捉されない場合は、最後に実行されます。
実行されないのは、JVMが終了したときだけです。
tryブロックの前に例外が発生した場合、最後にblockは常に実行されません。
finally
実行され、それは確かです。
finally
以下の場合は実行されません。
ケース1:
実行しているときSystem.exit()
。
ケース2:
あなたのJVM / Threadがクラッシュしたとき。
ケース3:
手動で実行が途中で停止したとき。
はい、そうです制御ステートメントなし防ぐことができますfinally
実行されてから。
これは参考例で、すべてのコードブロックが実行されます。
| x | Current result | Code
|---|----------------|------ - - -
| | |
| | | public static int finallyTest() {
| 3 | | int x = 3;
| | | try {
| | | try {
| 4 | | x++;
| 4 | return 4 | return x;
| | | } finally {
| 3 | | x--;
| 3 | throw | throw new RuntimeException("Ahh!");
| | | }
| | | } catch (RuntimeException e) {
| 4 | return 4 | return ++x;
| | | } finally {
| 3 | | x--;
| | | }
| | | }
| | |
|---|----------------|------ - - -
| | Result: 4 |
下記の変形では、return x;
スキップされます。結果はまだ4
:
public static int finallyTest() {
int x = 3;
try {
try {
x++;
if (true) throw new RuntimeException("Ahh!");
return x; // skipped
} finally {
x--;
}
} catch (RuntimeException e) {
return ++x;
} finally {
x--;
}
}
参照は、もちろん、それらのステータスを追跡します。この例では、参照を返します。value = 4
:
static class IntRef { public int value; }
public static IntRef finallyTest() {
IntRef x = new IntRef();
x.value = 3;
try {
return x;
} finally {
x.value++; // will be tracked even after return
}
}
finally
;ファイナライザ== thefinalize()
方法。 - jaco0646