例外について
この節の要点
- Javaプログラムでエラーが発生したとき、例外(Exception) がプログラム上で発行される。例外の発行を投げる と呼ぶ。
- 例外はエラーの種類ごとに用意されている。たとえば、初期化していないオブジェクトを利用した場合NullPointerExceptionが投げられる。
あるメソッドが、想定外の入力に対して正しい出力・処理ができない際に、うまく動作しないこと(エラー)に対する処理をどのように表現すればよいでしょうか。
基本的に、プログラムの無理な(不正な)動作はメモリ上のエラーにつながることが多く、その大半はOSが最終的にはセグメンテーション違反(Segmentation fault)などのエラーを代わりに出力して、プログラムがクラッシュして、強制終了します。
しかし、長時間動き続けるプログラムにおいては、このような強制終了を避けなければなりません。なぜならば、いつ強制終了するかわからないわけですから、つねにプログラムを監視して、必要であれば再起動させる必要が生まれます。これではプログラムを使う利点が台無しです。プログラマは、意図しない強制終了がないように、プログラムの処理を組み立てていく必要があるわけです。
ではどのようにエラー処理を実現すべきでしょうか。たとえば、Cであれば、関数が想定している入力以外を受け付けた際は、直ちにエラーを表す数値を返却するようにしておきます。 そして、呼び出した関数側で、返却された値がエラーを表しているかどうかチェックをし、エラーであれば、それに対応したエラー復帰処理を実施する、と言った流れでエラー処理を記述することが一般的です。
ですが、他の人が設計し作成した複数のライブラリを利用して、プログラムを作成する場合において、このようなエラー処理を書くことは、作成者おのおのの統一されている保証がないエラー処理を理解した上で改変しなければなりませんから、新たなエラーの温床になりますし、エラーの伝播を考慮する必要がうまれ、プログラムのフローが複雑化します。
例外(Exception) とは、エラー処理のための言語機能です。ここでは、単純に 例外=エラー として捉えてください。例外はプログラムの処理中のどこでもthrow(投げる)することができます。
例えば、図1に示すような赤字で示されるエラーがコンソールに表示された経験があると思います。

これが、例外によるエラー表示になります。このように例外が不用意に発生すると、標準出力にその例外がどの箇所でどのような内容で発生したかが表示され、プログラムがそれ以降の処理を待たず終了します。
以下によく現れる例外を示します。
- NullPointerException
- 参照型変数の中身が
nullのとき、オブジェクトが本来持つ変数やメソッドを利用すると投げられます。
- 参照型変数の中身が
- ArrayIndexOutOfBoundsException
- 配列を、配列の長さを越えたインデックスを使って利用すると投げられます。
- NumberFormatException
- 引数としてメソッドに渡された文字列データが、数値データに変換できない形式であるときに投げられます。
- RuntimeException
- より一般的なエラーであることを表す例外です。コンパイル時にわからない、実行時にのみわかるエラーが発生した時、投げられます。
具体的に、図2に示すようなプログラムを実行してみましょう。
Scanner scan = null; // 参照型の初期値を代入する
String input = scan.nextLine(); // Scannerオブジェクトが持つnextLineメソッドを呼び出す
System.out.println("next: " + input); // コンソールに表示する

図2のプログラムを実行すると、3行目で図3に示される例外が発生するはずです。図3で出力タブに表示された赤色文字がエラー出力であり、発生した例外の種類を示します。1行目を見るとNullPointerExceptionであることがわかります。また、エラーが発生した発生箇所をメソッド呼び出し毎に記録したログ(スタックトレース)も合わせて表示します。このスタックトレースの2行目を見ると、TextException.java:23を表示された、青文字が表示されていることが解ると思います。これは例外が発生したソースコード名と行数を表しており、この青文字をクリックすると、エディタペイン上で例外が発生した箇所にジャンプ(テキストカーソルが移動)します。
ここで、図2の3行目でNullPointerExceptionが発生すると、3行目以降は実行されず、プログラムが強制終了してしまいます。