【Java】例外処理
例外とは
例外とは、コンパイルではエラーにならないが、実行した際に発生するエラーのことです。 例えば、ファイルの読み込み処理でファイルが読み込めない、参照した値が存在しないなどさまざまな例外が考えられます。
後述しますが、プログラム上ではthrowという単語で例外が発生したことを表します。
そのため例外が発生することは、「例外が投げられる」や「例外がスローされる」と表現されます。
例外処理は、例外がスローされた場合にどのような処理を行うかを定義します。
検査例外と非検査例外
例外には、検査例外と非検査例外の 2 種類があります。
検査例外は、例外が発生した場合の処理、いわゆる例外処理を必ず定義しなければいけません。 言い方を変えると、例外処理を強制させる例外になります。
一方非検査例外は、例外処理を定義してもしなくてもよいという例外になります。 一般的には非検査例外が使用されることが多いです。
例外クラス
Java では、例外クラスというものがあり、クラスによってどのような例外が発生したかを表します。
すべての例外クラスは、Throwableクラスをスーパークラスとしており、大きく以下の 3 つの例外に分けられます。
Error
Errorクラスは、Throwableのサブクラスで、アプリケーション内で処理するべきでない重大な例外を表します。
そのためErrorクラスは、非検査例外に該当します。
通常のアプリケーション開発では、あまり使用しない例外だと思います。
Exception
Exceptionクラスは、Throwableのサブクラスで、すべての検査例外のサブクラスになります。
Exceptionのサブクラスには、以下のようなものがあります。
| 例外クラス | 説明 |
|---|---|
IOException | なんらかの入出力に関する例外 |
SQLException | デーベースへのアクセスや操作に関する例外 |
ClassNotFoundException | 指定したクラス名のクラスがなかった場合の例外 |
NoSuchFieldException | 指定したフィールド名がクラスになかった場合の例外 |
NoSuchMethodException | 指定したメソッド名がクラスになかった場合の例外 |
RuntimeException
RuntimeExceptionクラスは、Exceptionのサブクラスで、Error以外のすべての非検査例外のサブクラスになります。
RuntimeExceptionのサブクラスには、以下のようなものがあります。
| 例外クラス | 説明 |
|---|---|
IndexOutOfBoundsException | 配列などでインデックスが範囲を超えた場合の例外 |
NullPointerException | nullのオブジェクトに対して処理を実行しようとした場合などの例外 |
IlligalArgumentException | 不正な引数を渡した場合の例外 |
ArrayStoreException | 配列に不正なオブジェクトを追加しようとした場合の例外 |
ClassCastException | クラスがキャストできない場合の例外 |
例外処理の定義
try-catch
例外処理は、以下のようにtry、catchを使用して定義します。
try {
// 例外が発生する可能性のある処理
} catch (Exception e) {
// 例外時の処理
}catchには、実際に発生した例外クラスを指定します。
スーパークラスを指定することもできますが、一般的には発生した例外そのものを指定します。
検査例外がスローされる処理は、必ずcatchで例外処理を定義する必要があります。
非検査例外がスローされる処理は、catchするかは任意となります。
catchしなかった場合は、呼び出し元の処理へと例外が伝搬されます。
複数例外
例外が複数スローされる場合は、以下のように複数catchを指定するか、|で繋げます。
try {
// ...
} catch (IOException | SQLException e) {
// 例外時の処理
} catch (NullPointerException e) {
// 例外時の処理
}finally
finallyは、例外が発生してもしなくても必ず最後に行う処理を定義します。
ファイルのクローズ処理などで使用されます。
try {
// ...
} catch (Exception e) {
// 例外時の処理
} finally {
// 最後に実行する処理
}例外のスロー
throws
メソッドの定義で、どのような例外がスローされるかをthrowsを使って定義します。
public void doProcess() throws IOException, SQLException, NullPointerException {
//例外が発生する処理
}try {
doProcess();
} catch (IOException | SQLException e) {
// 例外時の処理
} catch (NullPointerException e) {
// 例外時の処理
}throw
throwは、意図的に例外をスローする場合に使用します。
public void doProcess() throws IOException, SQLException, NullPointerException {
if (!condition) {
throw new NullPointerException();
}
}独自例外
例外は、継承することで独自の例外を作成することができます。
基本的に、検査例外とする場合はExceptionを、非検査例外とする場合はRuntimeExceptionを継承します。
意味や用途の近い例外がある場合は、それを継承します。
コンストラクターは、必要なものだけ定義します。
以下はExceptionのコンストラクターを基に作成しています。
public class MyException extends RuntimeException {
private static final long serialVersionUID = 1L;
public MyException() {
super();
}
public MyException(String message) {
super(message);
}
public MyException(String message, Throwable cause) {
super(message, cause);
}
public MyException(Throwable cause) {
super(cause);
}
protected MyException(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}public void doProcess() throws MyException {
if (!condition) {
throw new MyException();
}
}try {
doProcess():
} catch (MyException e) {
// 例外処理
}