例外の継承を変えたら複数のcatchで到達不能エラーJavaTips 〜Javaプログラミング編

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

 Javaが提供している2つの例外クラスを用いて、自前の例外クラスを定義し、これを試すプログラムを下記のように作成しました。ご覧の通り、このプログラムは問題なく動作します。

【例1】正常に動作し、2つめのcatch句が用いられている 【例1】正常に動作し、2つめのcatch句が用いられている

 また、ここで、“自前の例外2”のMyBigExceptionの継承関係を変更して、MySmallExceptionと同様にしても、問題なく動作します。

【例2】同じ継承関係にしても正常に動作する 【例2】同じ継承関係にしても正常に動作する

 ところが、ここで、“自前の例外1”のMySmallExceptionの継承関係を変更して、MyBigExceptionと同様にすると、コンパイルエラーが発生してしまいます。これはどういうことでしょうか。

【例3】上位の同じ継承関係にするとコンパイルエラーになる 【例3】上位の同じ継承関係にするとコンパイルエラーになる

「到達不可能エラー」のチェックには限界がある

 一般に例外クラスを利用して複数のcatchを行う場合には、指定する例外に継承関係があれば、これを考慮して順番を決める必要があります。例えば、下記のようにNullPointerExceptionのスーパークラスであるRuntimeExceptionを先にcatchすると、「すでに処理されています」というエラーになってしまいます。

「すでに処理されています」というエラー 「すでに処理されています」というエラー

 この場合は、catch句の順番を変えるとエラーは解消されます。ところが、上記の【例3】は順番を変えてもエラーのままになります。これは、よく見ると分かりますが、catch句の順番を変えたところでMySmallExceptionに到達する可能性はないのですから、当然のことです。

 しかし、【例1】【例2】においても、よく見ると同じことが起こっていることが分かります。つまり、エラーにはなっていませんが、この場合も「MySmallExceptionに到達する可能性はない」のです。

 このことから、コンパイラによる、あるcatch句が「到達不可能かどうか」のチェックには限界があることがわかります。【例1】のように、2つの自前例外クラスの継承関係が異なる場合、チェックされないのはやむを得ないかもしれませんが、【例2】【例3】のように、2つの自前例外クラスの継承関係が等しい場合、スーパークラスがExceptionの場合にはエラーとなり、RuntimeExceptionの場合は、エラーにならないのです。

 どちらにしろ、到達する可能性のないcatch句は、コメントアウトするか削除する方が良いでしょう。

 Javaのコンパイル時のエラーチェックは非常に厳密であり「制御が渡らないことが明らかである文の存在を許さない」という特徴がありますが、複雑なcatch句においてはチェックされない場合もあり、その境界はややあいまいです。どちらにしろ、コンパイラにチェックされることを前提としたプログラミング作業はお勧めできないことが、今回の例から分かると思います。

Profile

RunDog.org

平野正喜


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

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

メールマガジン登録

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