読者です 読者をやめる 読者になる 読者になる

例外は基本投げずに処理し,できないならRuntimeExceptionを投げるべし

計算機 Java

異常系はだるい

異常系の処理は,本筋ではないし,大体同じ処理だから,読む際にノイズになって可読性をすごく下げる,特にC. システムコールを呼ぶ度にいろいろ書くのは面倒だ.

Javaの例外も大変だ

Javaの場合は,Exceptionがあるからちょっとはマシかと思いきや,そうでもない. 面倒くさいから,とりあえず上に投げとけやみたいにするとグチャクチャになってしまう.

Javaの仕様上,下から飛んできた例外は更に上に投げるか,自分のとこで処理しなければならない.しかし,他の人が書いたコードから発生した例外なんて,何が原因で起こったか分からないから,処理できやしない.

IDEに頼りきってコンパイルだけ通るコードにされたら,酷い目に遭う.Eclipseは次のように自動で例外処理を生成してくれる.

try {
    FileInputStream fi = new FileInputStream("foo.txt");
} catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

これがそのまま残ったら……考えたくもない.

例外は2種類ある

例外は2種類ある.

  1. 普通に起こりうる処理可能な例外
  2. 通常では起きない処理不可能な例外

前者は別に異常系ではない.いい例が思い浮かばないが,あるかないか分からないファイルを開こうと思ったらなかった場合などだ.ないならないで処理が別の処理をやる場合だ.

こういう場合は条件分岐を先にして,あまり例外を使うべきではないと思うが,ライブラリが例外を投げてくる場合は処理しないわけにはいかない.重要なのは上に投げずにその場で処理をすることだ.

後者は本当の異常系で,起動しようとしたら設定ファイルがなかったとか,ログを書き出そうとしたら権限がなかったとかだ.こういう場合はその場で処理できないからと,上に投げちゃうと,どこかで丸められてしまって困ったことになる恐れがある.

異常系にはRuntimeExceptionを使おう

本当の例外を投げたいときは,RuntimeExceptionを使おう.RuntimeExceptionはtry-catchでくくったり,throwsでスルーパスする必要はないので,知らない間に隠蔽されるおそれがない.

以下のように例外からRuntimeExceptionを作れる.

try {
    FileInputStream fi = new FileInputStream("foo.txt");
} catch (FileNotFoundException e) {
    throw new RuntimeException(e);
}

必要ならば最上位でcatchしてログに書き出すなりエラーメッセージを表示するなりすれば良いのだ.そうすれば異常系の処理が一箇所で良くなり,コードの見栄えも良くなる.ほぼほぼ起きない異常系の処理をコードのいたるところに埋め込んで乱雑になるのが防がれる.