なぜfinallyブロックを使用するのですか?


91

私の知る限り、次のコードスニペットはどちらも同じ目的を果たします。なぜfinallyブロックがあるのですか?

コードA:

try { /* Some code */ }
catch { /* Exception handling code */ }
finally { /* Cleanup code */ }

コードB:

try { /* Some code */ }
catch { /* Exception handling code */ }
// Cleanup code

これはC#に固有のものではなく、.Netの質問です
2010

1
java7ではもう必要ありません:AutomaticResourceManagement、try(new resourceDeclartion()){}
Kanagavelu Sugumar 2014年

回答:


139
  • 処理していない例外がスローされた場合はどうなりますか?(私はあなたが捕まえていないことを願っていますThrowable...)
  • tryブロックの内側から戻るとどうなりますか?
  • catchブロックが例外をスローするとどうなりますか?

finallyブロックは確認します、あなたが(明示的に全体のプロセスを中止するいくつかの方法を法)そのブロックを終了し、それが実行されます。これは、リソースの決定論的なクリーンアップにとって重要です。


48
必ずしも真実ではありません。(1)System.exit()呼び出しがある場合(2)tryまたはcatchブロックの1つに無限ループがある場合(3)コンピューターのプラグを抜く場合
NullUserException 2010

2
@Alon try {return 1; }最後に{retrun2; }あなたは2を得るでしょう
デニスC

19
@NullUserException:したがって、「モジュロいくつかの方法...」ビット
Jon Skeet

2
ジョンスキートはここに
スタックオーバーフローで

1
この投稿では、最終的に呼び出されない(まれな)条件について説明します。
カンダミール2017

13

(少なくともJavaでは、おそらくC#でも)tryブロックを。なしでcatch、ただしfinally。付きにすることも可能であることに注意してください。tryブロックで例外が発生すると、例外がfinally上位にスローされる前に、ブロック内のコードが実行されます。

InputStream in = new FileInputStream("somefile.xyz");
try {
    somethingThatMightThrowAnException();
}
finally {
    // cleanup here
    in.close();
}

7

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();
}

1
'finally'を使用せずに接続を閉じた場合はどうなりますか?
IstiaqueAhmed19年

5

最後に、常に実行されますが、キャッチ後のコードは実行されない場合があります。


1
何故なの!例外が適切に処理されると、コードは確実に実行されます。
モハマッドナディーム2010

1
@Nadeem:それが起こらないかもしれない3つの理由のために私の答えを見てください。
Jon Skeet 2010

2

アプリケーションが強制的に閉じられても、実行する必要のあるタスクがいくつかあります(メモリの解放、データベースの閉じ、ロックの解放など)。これらのコード行をfinallyブロックに書き込むと、例外がスローされるかどうかに関係なく実行されます。ない...

アプリケーションはスレッドのコレクションである可能性があり、スレッドをException終了しますが、アプリケーション全体ではない場合finallyがあります。この場合、より便利です。

finallyJVMの失敗、スレッドの終了など、実行されない場合があります。


1

スローされる可能性のある例外に関係なく実行するには、そのコードが必要だからです。たとえば、管理されていないリソースをクリーンアップする必要がある場合があります( 'using'コンストラクトはtry / finallyブロックにコンパイルされます)。


0

何があってもコードを実行したい場合があります。例外がスローされるかどうか。次に、を使用しfinallyます。


0

finally JVMがシャットダウンされない限り、常に実行されます。 finallyますが、クリーンアップコードを1か所に配置する方法を提供するだけです。

catchブロックにクリーンアップコードを配置する必要があるとしたら、面倒です。


0

catchブロックが例外をスローした場合、残りのコードは実行されないため、finallyブロックを作成する必要があります。


0

最後に、Javaのブロックを使用して、ファイルのクローズ、接続のクローズなどの「クリーンアップ」コードを配置できます。


プログラムが終了した場合(System.exit()を呼び出すか、プロセスを中止させる致命的なエラーが発生した場合)、finallyブロックは実行されません。


0

まだ下にスクロールしますか?どうぞ!

この質問は私にしばらく前に大変な時間を与えました。

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);
}

この場合、出力は次のようになります。

  • 最後にブロックする
  • ex.Message--それが何であれ。

例外をキャッチして他のレイヤーに再度スローすると(Funneling)、スロー後のコードが実行されないことは明らかです。これは、関数内の戻りが機能するのと同じように機能します。

これで、catchブロックの後にコードでリソースを閉じない理由がわかりました。finallyブロックに配置します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.