支援対象地域:札幌、仙台、関東、愛知、関西、広島、福岡


はじめに

実行時に想定外の事態が起きた場合に対処できるように「例外」についてご紹介します。


例外処理(1)

1.例外処理の必要性

プログラムを設計する上で、バグはあってはならないことです。 社会インフラを支える大規模システムにバグが生じると、大きな社会問題や損害賠償につながる可能性があります。

    《Javaにおけるエラーの種類》

  1. 文法エラー(コンパイルエラー)
  2. 文法間違いにより起こります。
    コンパイルで失敗します。
    例) セミコロン「;」忘れ、全角スペースの混在、変数名間違い 等
  3. 実行時エラー(例外)
  4. プログラム実行中に発生した異常事態により起こります。
    動作の継続ができなくなります。
    例) 0で割る、存在しないファイルのオープン 等
  5. 論理エラー
  6. 実行は問題なくできるが、期待した結果が得られない状況です。
    例) 式内の「+」を「-」と間違えて記述する 等

Javaでは、実行時に発生したエラーを「例外」と呼びます。
例外が発生しても例外処理を記述していないと、プログラムは強制終了されます。
稼働し続けるシステムは、「例外」によって強制終了することを未然に防ぐ必要があるため、「例外処理」が必要になります。
例外処理で例外が起きた場合の対処法を記述しておくことで、、プログラムは強制終了されることなく、実行を継続できます。

2.例外の種類

Javaで扱われる例外は、「checked 例外」と「unchecked 例外」の2種類に分類されます。
更に、Java APIで提供されている例外クラスは、3種類に分かれます。

《例外クラス》

【checked 例外 vs. unchecked 例外】
例外クラス 例外の種類 例外内容 例外処理
Errorクラス unchecked 例外 致命的で対応しようがないエラー
例) ハードウェアの故障、メモリ不足 等
任意
RuntimeExceptionクラス unchecked 例外 必ずしも発生の想定が必要でないエラー
例) 変数がnull、配列のインデックス外アクセス 等
任意
Exceptionクラス checked 例外 発生を想定して対処しなければいけないエラー
例) ファイル読み書き、ネットワーク接続 等
必須

これらの例外クラスは、次のような継承関係にあります。

Errorクラス、RuntimeExceptionクラス、Exceptionクラスをスーパークラスに持つ例外クラス(サブクラス)をいくつかご紹介します。

【様々な例外クラス】
スーパークラス サブクラス名 例外処理 説明
Errorクラス VirtualMachineError 任意 JVMが故障または、
動作を継続するのに必要なリソースが不足した場合に発生
RuntimeExceptionクラス ArithmeticException 任意 整数をゼロで除算した場合に発生
RuntimeExceptionクラス NullPointerException 任意 オブジェクトが必要な場合に、
nullに対して操作を試みた場合に発生
RuntimeExceptionクラス IndexOutOfBoundsException 任意 ある種のインデックスを範囲外で使用した場合に発生
Exceptionクラス IOException 必須 入出力(I/O)関連で何かしらの例外が発生した場合に発生
Exceptionクラス SQLException 必須 データベース・アクセス時にエラーがあった場合に発生
Exceptionクラス ParseException 必須 解析中に予想外のエラーがあった場合に発生
Exceptionクラス TimeoutException 必須 処理の結果待ち状態(ブロック操作)が、
タイムアウトによって失敗した場合に発生


例外処理(2)

Javaにおける例外処理方法を2種類ご紹介します。

    《例外処理の方法》

  1. try-catch-finallyブロックよる例外処理

  2. throwsキーワードによる例外処理

1.try-catch-finallyブロック

try-catch-finallyブロックは、tryブロックcatchブロックfinallyブロックで構成されます。

tryブロック
 例外が発生しそうな箇所をtryブロックで囲みます。

catchブロック
 例外発生時の処理をcatchブロック内に記述します。

finallyブロック
 例外発生に関わらず必ず実行したい処理をfinallyブロックに記述します。


try{
 例外が発生しそうな処理
} catch(例外クラス 変数名){
 例外発生時の処理
} finally{
 例外発生に関わらず必ず実行したい処理(データベースやファイルのクローズ処理 等)
}

尚、try-catch-finallyブロックは、全てのブロックを記述する必要はありません。
以下の組み合わせが可能です。

    記述可能組み合わせ
  • try-catch
  • try-finally
  • try-catch-finally

try-catch-finallyを使用したサンプルコードです。

public class Example {

 public static void main(String[] args) {
  int[] numArray = {10, 20, 30, 40};

  for(int i = 0 ; i < 5; i++) {
   try {
    System.out.print("numArray:" + numArray[i]);
    System.out.println("、" + (i + 1) + "回目ループ");
   } catch (ArrayIndexOutOfBoundsException e) {
    System.out.println((i + 1) + "回目のループで例外が発生");
   } finally {
    System.out.println("finallyの実行" + "¥n");
   }
  }

  System.out.println("End");
 }
}
実行結果
numArray:10、1回目ループ
finallyの実行

numArray:20、2回目ループ
finallyの実行

numArray:30、3回目ループ
finallyの実行

numArray:40、4回目ループ
finallyの実行

5回目のループで例外が発生
finallyの実行

End

2種類以上の例外は、catchブロックを複数記述することで対応できます。
次のサンプルコードは、catchブロックを複数記述することで複数の例外に対応させています。

public class Example {

 public static void main(String[] args) {
  int[] numArray = {0, 10, 20, 30, 50};
  int ans;

  for(int i = 0 ; i < 5; i++) {

   try {
    ans = numArray[i + 1] % numArray[i];
    System.out.print("余り:" + ans);
    System.out.println("、" + (i + 1) + "回目ループ");

   } catch (ArithmeticException e) { //1つ目のcatchブロック
    System.out.println((i + 1) + "回目のループで例外が発生");
    System.out.println("ゼロで割ることはできません。");
   } catch (ArrayIndexOutOfBoundsException e) { //2つ目のcatchブロック
    System.out.println((i + 1) + "回目のループで例外が発生");
    System.out.println("インデックスを範囲外で使用しています。");
   } finally {
    System.out.println("finallyの実行" + "¥n");
   }
  }

  System.out.println("End");
 }
}
実行結果
1回目のループで例外が発生
ゼロで割ることはできません。
finallyの実行

余り:0、2回目ループ
finallyの実行

余り:10、3回目ループ
finallyの実行

余り:20、4回目ループ
finallyの実行

5回目のループで例外が発生
インデックスを範囲外で使用しています。
finallyの実行

End

2.throwsキーワード

throwsキーワードは、例外が発生する可能性のあるメソッドを定義するときに指定します。

アクセス修飾子 戻り値 メソッド名(引数リスト) 例外クラスthrows名 {…}

「throws 例外クラス名」は、例外クラスがunchecked 例外の場合は省略可能です。 一方で、checked 例外で省略する場合は、メソッド内でtry-catch-finallyブロックを用いて例外処理を行う必要があります。

throwsキーワードを使う上で、一つ注意点があります。
それは、"throwsキーワードが記述されているメソッド側は"、例外処理をしなくてよいということです。つまり、"メソッドを呼び出す側"が、try-catch-finallyブロックを用いて例外処理をしなければならないということです。

  1. try-catch-finallyブロックよる例外処理
  2. 例外処理を自分で行う
  3. throwsキーワードによる例外処理
  4. 例外処理を呼び出し元に委ねる

まとめ

例外処理」についてご紹介しました。 お役に立てると幸いです。