RuntimeExceptionとExceptionの違い

ブログ2本目!!

今回はJavaの例外で、通常のExceptionとRuntime系Exceptionの違いと、バグの元となりそうな挙動について記載してみたいと思います。

 

まず、通常の例外の定義方法を以下に記載してみます。

f:id:daisuke6106:20141213204114p:plain

これは通常通りの挙動です。

 

処理内にて例外が発生する可能性がある場合、

・自身のメソッドの中で例外を処理

・呼び出し元に発生した例外を投げて丸投げする

を決めることができます。

 

以下の例では自分で作成したExceptionを継承した例外クラスをthrowしてみます。

f:id:daisuke6106:20141213212234p:plain

 当然ですが、throwsを取り除くとコンパイルエラーとなります。

f:id:daisuke6106:20141213212423p:plain

 

ではRuntimeExceptionを継承した例外クラスをthrowするように修正します。 

f:id:daisuke6106:20141213212546p:plain

  

上記のキャプチャを見るとわかりますが、throwする例外がRuntimeExceptionを継承した例外クラスである場合、throws宣言をしなくてもコンパイルが通ります。

  

この上でコーディングの時の注意点

現場で既存のコードを読んでいる際に例外をキャッチする場合、以下のようにExceptionや、Throwableにてキャッチするのをよく見ます。

また以下のような場合は稼働させても正しく動きます。

f:id:daisuke6106:20141213221458p:plain

 

ただし、呼び出し先メソッド(この場合、splitメソッド)に不具合があり、RuntimeExceptionを継承した例外クラスであるNullPointerException(通称ぬるぽ)が発生した場合、呼び出し元のcatchでExceptionもしくは、ThrowableはこのNullPointerExceptionをcatchしてしまいます。

f:id:daisuke6106:20141213221958p:plain

 RuntimeException系例外すらもキャッチするという要件を元に作成するのならいいのですが、通常RuntimeException系例外は「これ以上処理できないような致命的な異常が発生した」という状態であるためJVMや、フレームワーク等に処理方法を任せるのが本来の姿です。

 

よって、必ずcatchするときはExceptionはThrowableではなく発生する例外クラスをcatchしするべきです

 

ExceptionやThrowableでcatchしてしまうと、バグでNullPointerExceptionが発生しているにも関わらず、ログにNullPointerExceptionが発生している旨が表示されず、ハマるといったケースがあり、大変危険です。

 

自分でthrowした例外をキャッチする場合は、通常どおりcatchの中に入る。

f:id:daisuke6106:20141213223908p:plain

RuntimeException系例外クラスであるNullPointerExceptionが発生した場合は、JVMが例外を処理しコンソールにNullPointerExceptionが発生した旨が出力された。

f:id:daisuke6106:20141213223447p:plain

以上!!!!!