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

【Effective Java】項目59:チェックされる例外を不必要に使用するのを避ける

Java Effective Java

チェックされる例外はプログラマに例外の処理を強制させることができるので、プログラムの信頼性を大きく向上させることができます。 ただし、これを過剰に利用すると API が使いにくいものになってしまいます。

次の条件がすべて満たされる場合のみ、チェックされる例外を利用するべきです。

  • API を適切に利用したとしても例外の発生を防ぐことができない場合
  • 例外の補足を強制をすることで有益な回復処理が行える場合

この二つが満たされない場合、チェックされない例外が適切です。

もし、プログラマが次の二つの例外処理しか書けないのであればチェックされない例外が適切でしょう。

try {
   object.method();
} catch (TheCeckedExcetion e) {
   throw new AssertionError(); // 決して起こらない
}
try {
   object.method();
} catch (TheCheckedException e) {
   e.printStackTrace(); // どうしようもないのでエラーを出力して終了
   System.exit(1);
}

CloneNotSupportedException はこのテストに合格しません。

Cloneable を実装しないオブジェクトに対して clone() を呼び出すと CloneNotSupportedException がスローされますが、これはチェックされる例外なので例外処理が強制されます。 しかし、この例外は基本的に回復できません。

そのため、本来はチェックされない例外であるべきでした。

チェックメソッド

チェックされる例外をチェックされない例外に変更するための一つのテクニックはチェックメソッドを作ることです。

try {
    obj.action(args);
} catch(TheCheckedException e) {
    // 例外状態の処理
}

このようなコードがある場合、次のようにチェックメソッドを作成して利用するようにします。

if (obj.actionPermitted(args)) {
    obj.action(args);
} else {
   // 例外状態の処理
}

後者のほうが、よいコードになり API の柔軟性も向上します。

さらに、こうしておけばプログラマが「action は必ず成功す。失敗したらこのスレッドが終了してもよい」と思っているならば、単に

obj.action(args);

のように書くことができます。

これは項目58で説明したチェックメソッドと同じものになります。

チェックメソッドは項目58で述べたようにように同期化が必要な場合には利用できません。 呼び出しの間に他のスレッドが状態を変更してしまう可能性があるからです。