メソッドは RuntimeException、Exception、Throwable をスローしてはならない。これらの例外を処理するには、RuntimeException をキャッチする必要があるが、これは「ERR08-J. NullPointerException およびその親クラスの例外をキャッチしない」で禁止されている。また、RuntimeException をスローすると分かりにくいエラーにつながることがある。たとえばメソッドの呼出し側は例外がスローされた原因を調べることができず、例外状態から回復できないかもしれない。
Exception もしくは RuntimeException の特定のサブクラスの例外であれば、メソッドはスローしてもよい。単一のthrow文に対して専用の例外クラスを作成することも許される。
違反コード
以下のコード例の isCapitalized() メソッドは、引数に文字列を取り、先頭の文字が大文字、2文字以降がすべて小文字、というパターンである場合に true を返す。また、引数に null が渡されると、RuntimeException をスローする。
boolean isCapitalized(String s) { if (s == null) { throw new RuntimeException("Null String"); } if (s.equals("")) { return true; } String first = s.substring(0, 1); String rest = s.substring(1); return (first.equals(first.toUpperCase()) && rest.equals(rest.toLowerCase())); }
isCapitalized()メソッドの呼出し側でRuntimeExceptionがスローされたかどうかを判断するためには、「ERR08-J. NullPointerException およびその親クラスの例外をキャッチしない」に違反せざるをえない。
適合コード
以下の適合コードでは、特定の例外条件を示すために NullPointerException をスローしている。
boolean isCapitalized(String s) { if (s == null) { throw new NullPointerException(); } if (s.equals("")) { return true; } String first = s.substring(0, 1); String rest = s.substring(1); return (first.equals(first.toUpperCase()) && rest.equals(rest.toLowerCase())); }
入力がnullかどうかのチェックは冗長である。このチェックを削除したとしても、入力sがnullである場合にはs.equals("")の呼出しでNullPointerExceptionがスローされる。しかし、明示的にnullチェックを行うコードを書くことで、プログラマの意図が明確になる。コードが複雑になるほど、不変条件のチェックと適切なthrow文を明示的に書くことが重要になるであろう。
違反コード
以下の違反コード例では、doSomething メソッドの宣言において、throws 節に Exception クラスを指定している。
private void doSomething() throws Exception { //... }
適合コード
以下の適合コードでは、例外条件をより明確に表す例外クラスとして IOException を指定している。
private void doSomething() throws IOException { //... }
例外
ERR07-EX0: セキュリティポリシーに適合するために例外を無害化するようなクラスでは、無害化したい特定の例外をキャッチし、代わりに、より一般的な例外をスローすることが許される。その場合、セキュリティポリシーの内容にもよるが、RuntimeException、Exception、Throwableをスローすることがある。
リスク評価
runtimeException、Exception、Throwableをスローすると、意図した例外クラスだけをキャッチするはずが、意図しない例外クラスまでキャッチしてしまう。
ルール | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
---|---|---|---|---|---|
ERR07-J | 低 | 高 | 中 | P6 | L2 |
関連ガイドライン
MITRE CWE | CWE-397. Declaration of throws for generic exception |
参考文献
[Goetz 2004b] | |
[Tutorials 2008] | Unchecked Exceptions – The Controversy |
翻訳元
これは以下のページを翻訳したものです。
ERR07-J. Do not throw RuntimeException, Exception, or Throwable (revision 94)