throw命令
例外をスローする – throw命令- throw exclazz
- exclazz:例外オブジェクト
例外はキャッチ(捕捉)するばかりでなく、自分で投げることもできます(これを「例外をスローする」と言います)。メソッドの中で例外をスローする際には、メソッド定義でもthrows句(複数形)で発生する可能性のある例外を明示しなければなりません。複数の例外を発生する可能性がある場合には、例外をカンマ区切りで列記します。
public void sample() throws HogeException { throw new HogeException(); }
上のようなsampleメソッドを呼び出すには、これまでと同じくtry句による例外の処理が必須です。
try { TrySample t = new TrySample(); t.sample(); } catch (HogeException e) { e.printStackTrace(); }
自ら例外をスローする場合には、以下の点にも注意してください。
(1)適切な例外を選択する特に、検査例外/非検査例外いずれをスローするかを決めることは大切です。なぜなら、検査例外をスローするということは、利用者側にも例外処理を強制するということだからです。つまり、例外をキャッチしてもそのままログを吐き出し、アプリを終了するしかないのであれば、例外を強制する意味はないということです(非検査例外で十分です)。
(2)標準的な例外をできるだけ利用するアプリでもExceptionクラス、またはその派生クラスを継承することで、独自の例外クラスを定義することは可能です。しかし、Javaでは標準でよく利用する例外をさまざまに提供しており、これらは一般的な開発者にとって見慣れたものです。まずは、標準の例外を利用することで、例外の意味も把握しやすく、コードの可読性が向上します。
以下は、よく利用する例外です。
Javaの主な例外クラス | |
---|---|
例外 | 概要 |
NullPointerException | オブジェクトがnullである |
IndexOutOfBoundsException | インデックスが範囲外 |
UnsupportedOperationException | 要求された操作が未サポート |
IllegalArgumentException | メソッドに渡されたパラメーターが不正である |
ArithmeticException | 計算で例外的な条件が発生 |
assert命令
メソッドに不正な引数を渡した場合には、IllegalArgumentyException例外で呼び出し元に通知するのが定石です。しかし、protected/privateメソッドのように内部的に利用するメソッドで、引数の内容も保証される場合には、assert命令を利用することをお勧めします。
protected dpuble getCircle(double radius) { assert radius > 0; return radius * radius * Math.PI; }
assertメソッドはjavaコマンドで-eaオプションを付与した場合にだけ実行される命令で、与えられた式がfalseの場合に、AssertionError例外を発生します。
信頼性の高い文脈では、assert命令を利用することで、if/throw命令を除去できますので、コードの見通しが良くなります。
catchブロックの説明でも触れたように、Exceptionはすべての例外のスーパークラスで、「一般的な例外」という以上の情報を持ちません。例外の型だけで、ある程度例外の種類が識別できるよう、スローするのはExceptionクラスの個別の派生クラスとするべきです。
例外の再スローcatchブロックの中で、受け取った例外を再スローすることも可能です。
try { reader = new FileReader("C:/data.txt"); } catch (FileNotFoundException e) { throw e; }
補足した例外を自分で処理できない場合には、まずは呼び出し元に再スローするようにしてください。catchブロックを空にするなどしてしまうと、そもそも例外が発生したこと自体を確認できなくなってしまうので、絶対に避けるようにしてください。
受け取った例外をそのまま再スローするだけであれば、太字の部分は単に「throw;」と書いても同じ意味です。