私の知る限り、次のコードスニペットはどちらも同じ目的を果たします。なぜfinally
ブロックがあるのですか?
コードA:
try { /* Some code */ }
catch { /* Exception handling code */ }
finally { /* Cleanup code */ }
コードB:
try { /* Some code */ }
catch { /* Exception handling code */ }
// Cleanup code
Throwable
...)finally
ブロックは、どのようにそのブロックを終了しても(プロセス全体を明示的に中止するいくつかの方法を法として)、実行されることを確認します。これは、リソースの決定論的なクリーンアップにとって重要です。
(少なくともJavaでは、おそらくC#でも)try
ブロックを.なしでcatch
、ただし。付きにすることも可能であることに注意してくださいfinally
。ブロックで例外が発生すると、例外が上位にスローされる前にtry
、ブロック内のコードが実行されます。finally
InputStream in = new FileInputStream("somefile.xyz");
try {
somethingThatMightThrowAnException();
}
finally {
// cleanup here
in.close();
}
tryまたはcatchブロックで何が起こっているかに関係なく、とにかく実行したいコードを配置することをお勧めします。
また、複数のcatchを使用していて、すべてのcatchブロックに共通のコードを配置する場合は、これを配置する場所になりますが、try内のコード全体が実行されたことを確認することはできません。
例えば:
conn c1 = new connection();
try {
c1.dosomething();
} catch (ExceptionA exa) {
handleexA();
//c1.close();
} catch (ExceptionB exb) {
handleexB();
//c1.close();
} finally {
c1.close();
}
最後に、常に実行されますが、キャッチ後のコードは実行されない場合があります。
アプリケーションが強制的に閉じられても、実行する必要のあるタスク(メモリの解放、データベースの閉じ、ロックの解放など)があります。これらのコード行をfinally
ブロックに書き込むと、例外がスローされたかどうかに関係なく実行されます。いいえ...
アプリケーションはスレッドのコレクションである可能性があり、スレッドをException
終了しますが、アプリケーション全体ではない場合finally
があります。この場合、より便利です。
finally
JVMの失敗、スレッドの終了など、実行されない場合があります。
スローされる可能性のある例外に関係なく、そのコードを実行する必要があるためです。たとえば、管理されていないリソースをクリーンアップする必要がある場合があります('using'構文はtry/ finallyブロックにコンパイルされます)。
まだ下にスクロールしますか?どうぞ!
この質問は私にしばらく前に大変な時間を与えました。
try
{
int a=1;
int b=0;
int c=a/b;
}
catch(Exception ex)
{
console.writeline(ex.Message);
}
finally
{
console.writeline("Finally block");
}
console.writeline("After finally");
上記のシナリオでは何が印刷されますか?はい、それは正しいと思いました:
ex.Message--それが何であれ(おそらくゼロ除算を試みた)
最後にブロックする
ついに
try
{
int a=1;
int b=0;
int c=a/b;
}
catch(Exception ex)
{
throw(ex);
}
finally
{
console.writeline("Finally block");
}
console.writeline("After finally");
この印刷物は何でしょうか?何もない!catchブロックがエラーを発生させたため、エラーがスローされます。
優れたプログラミング構造では、このコードが別のレイヤーから処理されるという意味で、例外が集中します。このような場合を刺激するために、このコードをネストしてみます。
try
{
try
{
int a=1;
int b=0;
int c=a/b;
}
catch(Exception ex)
{
throw(ex);
}
finally
{
console.writeline("Finally block")
}
console.writeline("After finally");
}
catch(Exception ex)
{
console.writeline(ex.Message);
}
この場合、出力は次のようになります。
例外をキャッチして他のレイヤーに再度スローすると(Funneling)、スロー後のコードが実行されないことは明らかです。これは、関数内の戻りが機能するのと同じように機能します。
これで、catchブロックの後にコードのリソースを閉じない理由がわかりました。finallyブロックに配置します。
finally
JVMがシャットダウンされていない限り、常に実行されfinally
ますが、クリーンアップコードを1か所に配置する方法を提供するだけです。
catch
各ブロックにクリーンアップコードを配置する必要があるとしたら、面倒です。
何があってもコードを実行したい場合があります。例外がスローされるかどうか。次に、を使用しfinally
ます。
catchブロックが例外をスローした場合、残りのコードは実行されないため、finallyブロックを作成する必要があります。
最後に、Javaのブロックを使用して、ファイルのクローズ、接続のクローズなどの「クリーンアップ」コードを配置できます。
プログラムが終了した場合(System.exit()を呼び出すか、プロセスを中止させる致命的なエラーが発生した場合)、finallyブロックは実行されません。