Javaが提供している2つの例外クラスを用いて、自前の例外クラスを定義し、これを試すプログラムを下記のように作成しました。ご覧の通り、このプログラムは問題なく動作します。
また、ここで、“自前の例外2”のMyBigExceptionの継承関係を変更して、MySmallExceptionと同様にしても、問題なく動作します。
ところが、ここで、“自前の例外1”のMySmallExceptionの継承関係を変更して、MyBigExceptionと同様にすると、コンパイルエラーが発生してしまいます。これはどういうことでしょうか。
一般に例外クラスを利用して複数のcatchを行う場合には、指定する例外に継承関係があれば、これを考慮して順番を決める必要があります。例えば、下記のようにNullPointerExceptionのスーパークラスであるRuntimeExceptionを先にcatchすると、「すでに処理されています」というエラーになってしまいます。
この場合は、catch句の順番を変えるとエラーは解消されます。ところが、上記の【例3】は順番を変えてもエラーのままになります。これは、よく見ると分かりますが、catch句の順番を変えたところでMySmallExceptionに到達する可能性はないのですから、当然のことです。
しかし、【例1】や【例2】においても、よく見ると同じことが起こっていることが分かります。つまり、エラーにはなっていませんが、この場合も「MySmallExceptionに到達する可能性はない」のです。
このことから、コンパイラによる、あるcatch句が「到達不可能かどうか」のチェックには限界があることがわかります。【例1】のように、2つの自前例外クラスの継承関係が異なる場合、チェックされないのはやむを得ないかもしれませんが、【例2】と【例3】のように、2つの自前例外クラスの継承関係が等しい場合、スーパークラスがExceptionの場合にはエラーとなり、RuntimeExceptionの場合は、エラーにならないのです。
どちらにしろ、到達する可能性のないcatch句は、コメントアウトするか削除する方が良いでしょう。
Javaのコンパイル時のエラーチェックは非常に厳密であり「制御が渡らないことが明らかである文の存在を許さない」という特徴がありますが、複雑なcatch句においてはチェックされない場合もあり、その境界はややあいまいです。どちらにしろ、コンパイラにチェックされることを前提としたプログラミング作業はお勧めできないことが、今回の例から分かると思います。
Copyright © ITmedia, Inc. All Rights Reserved.