Java基礎ー例外処理

Javaの例外処理の基本

例外とは

プログラムを実行する最中に発生するエラー(Exception)のこと。

Javaにおけるプログラムの実行中に発生するエラーには、大きく分けて2つの種類が存在する。
実行環境のトラブルなどプログラムからは対処しようのない事態を表すエラー(Error)と、プログラムが対処できる例外(Exception)の2つ。

例外はさらに、検査例外と非検査例外に分かれる。
検査例外(Exception):例外処理を記述したかをコンパイラが検査する例外
非検査例外(RuntimeException):例外処理を記述したかどうかをコンパイラが検査しない例外

Object
|
|---Throwable
       |
       |---Error
       |
       |---Exception
               |
               |---RuntimeException

Error, Exception, RuntimeExceptionにそれぞれに、例外の原因に即した子クラスが存在する。
それぞれについて、以下のように分類できる。

クラス 説明
Error JavaVM で検出される致命的エラー。例外処理を記述しても処理を継続できないことが多い。
RuntimeException 非検査例外。プログラムの不具合に起因する例外で、不具合により起きるものが多い。
Exception 検査例外。プログラムの不具合とは関係なく、状況によっては発生しうる例外で、例外処理を記述しないとコンパイルエラーとなる。

例外クラス

例外クラスは、自分で定義して作成することもできる。

検査例外とするクラスは java.lang.Exception クラスから派生させ、 非検査例外とするクラスは java.lang.RuntimeException クラスから派生させる。

public class MyException extends RuntimeException {
    @Override
    public MyException(String message){
        super(message);
    }
}

例外のスロー

例外を自分で発生させたい場合は例外をスローすることができる。

throw 発生させたい例外のインスタンス

public void doSomething(){
    throw new RuntimeException("例外をスローするぞ!");
}

検査例外が発生しうるメソッド

検査例外が発生しうる処理のあるメソッドには、メソッド宣言時にthrows句で発生しうる検査例外を明示する必要がある。

public void doSomething() throws IOException {
    // IOExceptionが発生するかもしれない処理
}

throws句のあるメソッドを呼び出すメソッドでは、後述の例外処理が義務付けられる。

public void hello(){
    try {
        doSomething();
    } catch (IOException e) {
        // 例外処理
    }
}

上記のhelloメソッドでも例外処理を行いたくない場合、helloメソッドを呼び出すメソッドが別で存在している場合に限り、helloメソッドにthrow句を付与することで、例外を伝播させることができる。

public void hello() throws IOException {
    doSomething();
}

例外処理

Javaの例外処理はtry-catchで行う。
catchの引数には、例外処理を行いたい例外クラスを指定する。
tryブロックの中で例外が発生しうる処理を記述し、catchブロックの中で例外が発生した際の処理を記述する。

例外処理において、finallyブロックは必ずしも必要ではない。
例外が発生した場合も、発生しなかった場合も共通で行いたい処理がある場合にfinallyブロックに処理を記述する。

try {
  // try ブロック
} catch (Exception e) {
  // 例外処理
} finally{
  // 例外の発生有無に関わらず、必ず行いたい処理
}

catchには|で繋いで複数の例外クラスを記述することができる。
前に書いた例外からチェックされるため、より子供のクラスから記述する。

try {
  // try ブロック
} catch (IOException|Exception e) {
  // 例外処理
} finally{
  // 例外の発生有無に関わらず、必ず行いたい処理
}