【Java】例外処理

概要

Javaでは、プログラム中で発生したエラーを「例外(Exception)」として定義する。
try-catch文は、例外が発生した際に、そのエラーを掴む(キャッチする)ために利用する。
try-catch文を利用することで、プログラムの実行中に発生したエラーの内容に応じて、特別な処理を指定できる

注意点

・try、catch、finally内で宣言した変数はその中でしか使えない
・try、catch内でreturnをしてもfinallyを実行してからreturnされる
入れ子にした場合、finallyは中と外どちらも通る

使い方

基本
try {
    // 例外が発生する可能性のある処理
} catch (NumberFormatException e) {
    // エラーが発生した場合の処理
} catch (ArithmeticException | NullPointerException e) {
    // エラーの内容で処理を分けることができる
    // 複数のエラーをまとめてキャッチ可能
} catch (Exception e) {
    // Exceptionはどんなエラーもキャッチ
} finally {
    // 必ず最後に実行する処理
}
入れ子

入れ子にした際の処理順 ※finallyをすべて通る

強制エラー(throw)

・throw newで強制的にエラーを発生させる
・エラーメッセージを指定できる
・e.getMessage()で設定したエラーメッセージを取得できる

public Integer calcNumber(String value) {
    try {
        throw new NumberFormatException("0は入力不可能です。");
    } catch (NumberFormatException e) {
        System.out.println(e.getMessage());
    }
    return null;
}
呼出元にキャッチの処理を強制する(throws)

メソッド名の後ろにthrowsを記載することで、例外処理をメソッド内でなく呼出先で行わせることができる。

public static void test1(){
    try {
        test2();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    return;
}
public static void test2() throws FileNotFoundException  {
    FileReader r = new FileReader("sample.txt");
    return;
}

point

エラーになった時点で呼出元のキャッチに遷移する

【メソッド内と呼び出し元にキャッチがある場合の処理順】

point

エラーがあっても呼出元のキャッチに行かない(呼び出し元のtry-catchが無駄)

try-with-resources

try-with-resources文では、tryブロックの中で利用したオブジェクトをtryブロックが終了した時に自動的にcloseするという処理を行ってくれるためfinally句でのリソースをcloseする記述が不要になる。
tryの後ろのかっこにresource (リソース)を記述する。
リソースとは、AutoCloseableインターフェースまたはCloseableインタフェースを実装したクラスをインスタンス化した変数。
リソースが複数ある場合はセミコロンで区切る。
※Java7以降

try (例外処理が必要なオブジェクトの作成) {
    オブジェクトを利用して処理を行う
} catch (例外クラス 変数) {
    例外が起きた時の処理
}

【try-with-resourcesを使わない例】

    public void test() {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader("hoge.txt"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                // closeにまたtry-catchが必要
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return;
    }

【try-with-resourcesを使用した例】

    public void test() {
        try(BufferedReader br = new BufferedReader(new FileReader("hoge.txt"))) {

        } catch (IOException e) {
            e.printStackTrace();
        }
        return;
    }

例外の種類

NullPointerException 値がnullのオブジェクトへアクセスすると発生
IOException ファイルや通信などのIOに関する問題があった場合に発生
FileNotFoundException ファイルが見つからない場合に発生
IllegalArgumentException 不正な引数の場合に発生
IndexOutOfBoundsException 配列やリストのサイズを超えてアクセスした場合に発生

オリジナルの例外を作成

「Exception」を継承してクラスを作成する

エラーメッセージを固定にする場合
public class SampleException extends Exception{
    // コンストラクタにエラーメッセージを記載しておく
    public SampleException() {
        super("SampleExceptionのエラーメッセージ");
    }
}

使用方法

public static void test1(){
    try {
        throw new SampleException();
    } catch (SampleException e) {
        System.out.println(e.getMessage());
    }
    return;
}
エラーメッセージを指定する場合
public class SampleException extends Exception{

    public SampleException(String msg) {
        super(msg);
    }
}

使用方法

public static void test1(){
    try {
        throw new SampleException("エラーメッセージです");
    } catch (SampleException e) {
        System.out.println(e.getMessage());
    }
    return;
}