Javaに関する様々な情報をご紹介します。

2try、catch、finally

Javaに関する様々な情報をご紹介します。

try、catch、finally

このページではJavaでの例外処理におけるtry、catch、finallyの使用方法について説明します。

try、catch、finallyの使用方法

try、catch、finallyはJavaでの例外処理における基本事項です。以下の枠内のフォーマットにより構成されます。

try {
  例外をスローする可能性のある処理
} catch (例外クラス型 引数名) {
  例外処理(例外ハンドラ)
} finally {
  最後に必ず実行される処理
}

try { 例外をスローする可能性のある処理 }
try節では例外をスローする可能性のある処理を{ }で囲みます。try節で囲まれた処理の中で例外が発生した場合、Java実行時環境は該当する例外ハンドラが書かれていないか捜しにいきます。
catch (例外クラス型 引数名) { 例外処理(例外ハンドラ) }
catch節ではスローされた例外に対する処理を行う例外ハンドラを記載します。スローされた例外オブジェクトとcatch節に記載された例外クラス型が合致した場合、Java実行時環境はそのcatch節の例外ハンドラを実行します。catch節に記載された引数名を利用して該当する例外オブジェクトの情報を参照することもできます。
finally { 最後に必ず実行される処理 }
finally節は例外が発生するしないにかかわらず必ず実行したい処理を記載する時に使用します。例えばファイルオープン処理を行う場合、オープン処理が成功する・成功しないにかかわらずファイルクローズ処理を行わなければならないとします。そのような時にfinally節にファイルクローズ処理を記載します。finally節は必須項目ではありません。

【例1】任意の例外処理を行った例です。

class ExException5{
    public static void main (String[] args) {
        try {  //(1)try節
            int x = Integer.parseInt(args[0]);
            System.out.println("答えは" + (100/x));
        } catch(ArithmeticException e) {  //(2)catch節
            System.err.println("エラー" + e.getMessage());
        } finally {  //(3)finally節
            System.out.println("This program was finished.");
        }
    }
}

解説1

  1. (1)例外をスローする可能性のある処理をtry節内に記載します。100を除算する変数xが0の場合、例外ArithmeticExceptionがスローされます。
  2. (2)キャッチする例外オブジェクトの例外クラス型とその例外オブジェクトをキャッチした場合の例外処理を記載します。ここでは、例外ArithmeticExceptionをキャッチした場合、getMessageメソッドで例外オブジェクトに含まれるメッセージを出力する処理を記載します。
  3. (3)例外をスローする、しないに関わらずfinally節内を実行します。finally節では「This program was finished.」を表示します。

実行結果1:正常処理

D:\JAVA>java ExException5 10
答えは10
This program was finished

D:\JAVA>

実行結果1:例外処理

D:\JAVA>java ExException5 0
エラー/ by zero   # getMessageの実行
This program was finished

D:\JAVA>

例外の処理フロー

ここでは例外処理の処理フローについて説明します。

例外の処理フロー
【例外が発生しない場合】
例外が発生しない場合は例外ハンドラを実行せず、finally処理を実行した後、その後に続く処理を実行します。
処理フロー(例外が発生しない場合)
【例外が発生する場合(例外ハンドラがキャッチされた場合)】
Java実行時環境が例外ハンドラをキャッチした場合、例外ハンドラ、finally処理の順に処理が行われます。その後、その後に続く処理を実行します。
処理フロー(例外が発生する場合(例外ハンドラがキャッチされた場合))
【例外が発生する場合(例外ハンドラをキャッチしない場合)】
Java実行時環境が例外ハンドラをキャッチしない場合、finally処理を実行し、Javaのデフォルトのエラー処理を行った後、プログラムを終了します。
処理フロー(例外が発生する場合(例外ハンドラをキャッチしない場合))

catchの使用方法(応用)

1. catchは複数指定可能

catchはスローされる例外オブジェクトにあわせ複数指定することができます。上から順に実行され、1つのcatch節が実行されるとそれ以降のcatch節は実行されません。

【例2】catchを複数指定した例です。

class ExException6 {
    public static void main (String[] args) {
        try {
            int x = Integer.parseInt(args[0]);  //(1)
            System.out.println("答えは" + (100/x));  //(2)
        //ArithmeticExceptionの例外ハンドラ
        } catch(ArithmeticException e) {
            System.err.println("ArithmeticExceptionをキャッチ");
        //NumberFormatExceptionの例外ハンドラ
        } catch(NumberFormatException e) {
            System.err.println("NumberFormatExceptionをキャッチ");
        } finally {
            System.out.println("This program was finished");  //(3)
        }
    }
}

解説2

  1. (1)コマンドラインから入力された値をint型に変換し、変数xに代入します。コマンドラインから入力された値が数値に変換できない場合(文字列など)例外NumberFormatExceptionをスローします。
  2. (2)100を変数xで除算します。xが0の場合、例外ArithmeticExceptionをスローします。
  3. (3)例外が発生する、しないにかかわらずfinally節を実行し、「This program was finished」を表示します。

実行結果2

D:\JAVA>javac ExException6.java

D:\JAVA>java ExException6 abc
NumberFormatExceptionをキャッチ  # 例外NumberFormatExceptionが発生!!
This program was finished

D:\JAVA>java ExException6 0
ArithmeticExceptionをキャッチ  # 例外ArithmeticExceptionが発生!!
This program was finished

D:\JAVA>

2. catchは例外クラスの継承関係を意識する。

catch節で指定する例外クラス型には例外クラスの継承関係が適用されます。例外クラスIOExceptionは入出力関係の例外クラスの中でスーパークラスです。例外クラスFileNotFoundExceptionは入出力関係の例外クラスの中でファイルが存在しない時に発生する例外クラスです。try節でFileNotFoundExceptionが発生した場合catch節の例外クラス型でIOExceptionを指定することによりその子孫クラスであるFileNotFoundExceptionをキャッチすることができます。

このことは例外クラスのスーパークラス(Throwableクラス)の近い場所に位置するExceptionクラスを指定するとほぼすべての例外をキャッチできると言えます。しかしこの方法は予期せぬ例外までもキャッチしてしまいあまり推奨されていません。デバッグ目的以外では例外クラス型にExceptionクラスを指定するのは避けるべきです。

catch節を複数指定する場合は例外クラスの継承関係を意識する必要があります。より具体的な例外クラスを前に指定しない場合、コンパイルエラーとなります。例外クラスFileNotFoundExceptionと例外クラスIOExceptionを指定する場合、FileNotFoundExceptionを先に指定する必要があります。

・・・・・・・・・・・・・・・・・・・・・・
・・・・・・・・・・・・・・・・・・・・・・

//より具体的な例外クラスを先に指定
} catch(FileNotFoundException e) {
    System.err.println(e.getMessage());
} catch(IOException e) {
    System.err.println(e.getMessage());
}

・・・・・・・・・・・・・・・・・・・・・・
・・・・・・・・・・・・・・・・・・・・・・

3. 例外がキャッチされない場合はデフォルトの例外処理を実施する。

catch節で指定されている例外クラス以外の例外が発生した場合、Javaはデフォルトの例外処理を実行します。デフォルトの例外処理とはあらかじめ用意されているエラーメッセージを表示し、プログラムを終了させます。

2try、catch、finally