プログラマにとって例外処理は避けて通れない厄介な問題です。今回はJavaでの例外処理について考えてみたいと思います。
はじめに、Javaの例外処理のための仕組みを整理しましょう。
例外を発生させるコード(メソッド・コンストラクタ・もしくは自分で発生させる)を使う部分をtry節で括り、その例外への対処をcatch節に、例外の有無に関わらず行う処理をfinally節に書きます。
try { // 例外を発生させるコード } catch (SomeException1 e) { // SomeException1が発生した場合の処理 } catch (SomeException2 e) { // SomeException2が発生した場合の処理 } finally { // 例外の有無に関わらず行う処理 }
異なる例外を処理するcatch節は複数並べて書くことができますが、発生した例外に対応するcatch節かどうかは上から順に判定されることになっているため、ある例外を処理するcatch節の次にそのサブクラスに当たる例外を処理するcatch節を書くことはできません。(到達不能コードとなります)
この複数書ける、というところが重要です。つまり対処する例外とその対処方法を選択できるということですね。
メソッドまたはコンストラクタが発生させる(投げる・スローするという)例外を宣言します。
メソッドまたはコンストラクタが例外をスローする可能性がある場合、その例外、もしくはそのスーパークラスである例外をすべて宣言する必要があります。ただし、チェックされない例外(後述)は宣言しなくても構いません。
自分で例外をスローするときに使います。Throwableクラス(Exceptionクラスのスーパークラス)のサブクラスであればスローすることができます。
例外そのものを表すクラスです。例外にはチェックされる例外とチェックされない例外があります。
端的に言えば、チェックされる例外とは「なんらかの対処をしないとコンパイルできない例外」で、チェックされない例外とは「対処しなくてもコンパイルできる例外」です。
ここに重要なポイントがあります。
つまりチェックされる例外は、なんらかの対処をすべき・あるいは回復可能な余地があるかもしれない例外を表し、チェックされない例外は、対処する意味が無い・もしくは回復不可能な例外を表すということなのです。(少なくともそういう意図を持って言語設計されています)
アサーション/表明は例外処理機構そのものではありませんが、安全で見やすいコードを書くために役立ちます。
assertに続けて条件式と必要であればメッセージを書きます。実行時にアサーションが有効であり、かつ条件式が偽であればAssertionErrorが発生します。
ちなみにAssertionErrorはThrowableのサブクラスであるため、自分でスローすることもできます。
AssertionError <- Error <- Throwable
まずは例外処理のための仕組みをまとめました。次回から具体的な方針について見ていきたいと思います。