finallyを使う場面と、finallyでしてはいけないことJavaTips 〜Javaプログラミング編

» 2006年11月22日 10時00分 公開
[平野正喜@IT]

 finallyは、try-catch構文において、例外の有無や処置に限らずに行いたいことがある場合に指定する句であり、Javaの例外処理の柔軟性を高めます。プログラムが例外によって中断しても、catchによって捕捉されて続行しても、あるいは、正常に進んでも、finallyによって同等の処理を行うことができます。よって、例外が付き物の通信処理やファイル処理の後始末などに役立ちます。

 しかし、finallyを用いると、通常のtry-catch構文の場合に比べて、動作が複雑になりますので、使うべき場面かどうかを考えるのが肝心です。 また、finallyを用いると動作テストが難しくなります。catchが1つしかない場合でも、下記の全パターンを試す必要があるからです。

  1. 例外が発生せずに進み、finallyの内容が実行されるパターン
  2. 例外が発生して、catchされ、その後でfinallyの内容が実行されるパターン
  3. 例外が発生したが、catchされず、finallyの内容が実行されてから例外終了となるパターン

finallyの中から外へ制御を移す処理は不可

 そして、finallyの中から外へ制御を移す処理は、finallyの中で実行すべきではないので注意が必要です。上記のパターン3が正しく行われなくなってしまいます。具体的には、下記の文、メソッドが該当します。

  • break、continue、return
  • System.exit(int)

 これらは、javacでコンパイルした場合にはエラーや警告の対象にはなりません。しかし、Eclipseを用いると、break、continue、returnについて「finallyブロックは正常に完了しません。」という警告が表示されます。下図はreturnの場合です。

「finally」に警告が表示されている 「finally」に警告が表示されている

 ただし、System.exit(int)を使った場合や、break、continue、returnがif文などの中にある場合はチェックされません。警告に頼るのは危険です。

 一例として、「例外の有無にかかわらず、ヒープメモリの消費量が20%を超えたら無条件に終了」することを意図したプログラムを作成しました。このプログラムでは、17行目からのfinallyの中で、breakを実行していますが、if文の中なので、警告が出ません。そして、下図のとおり実行すると、11行目にバグがあり、ゼロによる除算から例外が発生します。ところが、もしも、その前に、ヒープメモリの消費量が20%を超えていたら、19行目のbreakが実行され、例外が消されてしまうのです。

「finally」に警告が表示されず、不正な動作となる可能性があるプログラム 「finally」に警告が表示されず、不正な動作となる可能性があるプログラム

 この例からも、finallyブロックが正常に完了しないプログラムは避けるべきことが分かります。

Profile

RunDog.org

平野正喜


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。