【本サイトではGoogleアドセンス、または、アフィリエイト広告を利用しています。】
例外処理とは?
例外処理はプログラムを書く上で重要な構文です。
例外処理とは、想定していない結果が発生した時に行う処理のことです。
プログラムの書き方としては間違っていなくとも、
変数に入る値や計算方法によって、実行したタイミングで
つじつまがあわない想定外の結果になることがあります。
何もしない場合、Javaが例外を返して、プログラム(システム)は
即時に停止してしまいますが、例外処理を使うことで、
例外が発生した時の動きを自分で指定することができます。
Exceptionとは?
Javaのプログラムを実行した時に発生するすべてのエラーや例外は、
Throwableクラスというスーパークラスに集約されます。
また、発生したエラーや例外の内容に従って、
Throwableを継承した各種サブクラスに細かく分類されます。
Exceptionとは、プログラムを実行して例外が発生した時に作成される
Throwableのサブクラスです。
想定外となった結果の内容や発生場所などの情報が
Exceptionの中にオブジェクトとして保存されます。
では、実際にエラーを発生させてみましょう!
大きさ「5」の配列を用意して、要素「5」に値を入れてみます。
package example;
// クラス:メイン処理実行用
public class Example {
// メイン処理
public static void main(String[] args) {
int[] numArray = new int[5];
numArray[5] = 1;
}
}
実行するとこんなエラーが出ます。
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
at example.Example.main(Example.java:11)
配列の要素数を超えた場所に値を入れようとしたのでエラーになりました。
コンソールに表示された内容はJavaが作成したExceptionが持つ情報です。
また、さらに例外の中にも、以下のように様々な種類があります。
Exceptionは例外を総括したスーパークラスで、
Javaは例外の種類に応じてさらにサブクラスに分類された結果を返します。
例外の種類 | 説明 |
---|---|
NullPointerException | 値が入っていない変数を使おうとした。 |
ArrayIndexOutOfBoundsException | 要素数を超える場所を使おうとした。 |
ClassCastException | クラスを指定の型にキャストできなかった。 |
ClassNotFoundException | クラスが見つからない。 |
IOException | 入力・出力ができなかった。 |
SQLException | SQLが実行できなかった。 |
BufferOverflowException | バッファが足りなくなった。 |
例外が起こったよ!だけでは何が原因なのかわからないですが、
このサブクラス名を見るだけでおおよその原因を予測できます。
例外が起こると必ずこれらのExceptionクラスが
作成されることを覚えておきましょう!
try~catchの書き方
例外について理解したところで、発生した例外を処理する方法を覚えましょう。
発生した例外はtryとcatchの構文を使って受け取ることができます。
tryの中に書かれた処理を実行して、
例外が発生した時はcatchの中に書いてある処理を実行する
という仕組みになっています。
try {
// 実行したい処理
}
catch (Exceptionクラスの型 変数名) {
// 例外が発生した時の処理
}
状況次第で例外が発生することが想定される処理に関しては、
基本的にtry~catchの構文で囲んでおいて、
例外処理もいっしょに用意しておくことが望ましいです。
throwとは?
throw(スロー)とは、
受け取った例外処理を上位のプログラムへ渡すことです。
例外が発生した場合、catchで受け取ることはできますが、
そのまま何もせず終了してしまうと、
誰も例外が発生したことに気づかない状態になります。
Exceptionの中には例外に関する詳細な情報が入っているので、
catchの中でthrowして、最終的にシステムのログファイルや
コンソール上に情報を出力させるのが一般的です。
書き方は以下です。
try {
// 実行したい処理
}
catch (Exceptionクラスの型 変数名) {
// 例外が発生した時の処理
// 例外を上位のプログラムへ渡す
throw 変数名;
}
throw先は、上位のプログラムということですが、
具体的には1ブロック上のプログラムに渡すことになります。
上位のプログラムでcatch処理を記載していない場合は、
そのままJavaの上位プログラムまで引き渡されて
コンソールにExceptionの内容が出力されます。
finallyとは?
finally(ファイナリー)とは、
最後に必ず実行したい処理を記載する為の構文です。
最後といっても、プログラム全体の最後ではなく、
プログラムのブロック単位で使うことができます。
例外が発生した場合、本来実行するはずの処理は中断されて、
catchの中の処理へスキップする為、最後に実行する予定だった処理を
通らずに、プログラムが終了することになります。
例えば、データベースへ接続してデータ登録をしている場合、
例外発生によって処理が中断されると、データベースとの接続を切断しないまま
強制的にプログラムが止まってしまいます。
この場合、データベース側から見ると登録処理を実行中ですが、
プログラム側から見ると処理は終了していることになり、
同期が取れず以降の処理が継続できない問題が発生します。
このような問題が起こるのを防ぐ為、
最後に必ず実行する必要のある処理については、
finallyを使って記載しておくのが一般的です。
書き方は以下です。
try {
// 実行したい処理
}
catch (Exceptionクラスの型 変数名) {
// 例外が発生した時の処理
}
finally {
// 最後に実行する処理
}
このようにfinallyの中に処理を書いておくことで、
tryの中の処理が正常に実行できた時も、例外が発生してcatchの処理が実行された時も、
必ずfinallyの中の処理が最後に実行されるようになります。
例外処理の使い方(サンプルコード)
それでは、例外処理の使い方をサンプルコードで見ていきましょう。
最初に使った配列要素の範囲外に値を入れる例を使います。
処理結果判定用のフラグを設けて、正常終了ならtrue、
異常終了ならcatch処理でfalseを代入し、finallyの中で結果を出力します。
package example;
// クラス:メイン処理実行用
public class Example {
// メイン処理
public static void main(String[] args) {
// 処理結果判定用
boolean processFlg = true;
int[] numArray = new int[5];
try {
numArray[5] = 1;
System.out.println("配列に値を入れました!");
}
catch (Exception e) {
System.out.println("例外が発生しました!");
processFlg = false;
throw e;
}
finally {
if (processFlg) {
System.out.println("プログラムが正常に終了しました!");
}
else {
System.out.println("プログラムを中断しました!");
}
}
}
}
実行結果は以下です。
例外が発生しました!
プログラムを中断しました!
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
at example.Example.main(Example.java:16)
配列に値を入れた後のメッセージはコンソール上に出力されていないので、
例外を検知してしっかり処理を中断できたことがわかります。
catchの中でthrowをしても、finallyの処理は必ず通るところも
ポイントとして覚えておいてください。
例外処理 まとめ
Javaの例外処理について以下説明しました。
・例外処理について
・Exceptionについて
・try~catchの書き方
・throwの書き方
・finallyの書き方
プログラムを書いていると、例外処理を書くことをおそろかにしがちです。
しかし、例外が発生した後の処置までしっかり書くことも
品質の良いプログラムを目指す上では重要なことです。
特にデータベースやファイルを取り扱う処理では必須の構文になるので
しっかりマスターしておきましょう!