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

1はじめての例外

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

はじめての例外

このページではJavaプログラムの特徴的な機能の一つである例外について説明します。

例外の概要

例外とはプログラム動作における予期せぬ事象(エラー)のことを言います。Javaでは例外が発生した時、あらかじめ用意されているエラーメッセージ(Exception in thread "main" java.lang.ArithmeticException ・・・など)を表示しプログラムを終了します。これがJavaのデフォルトの例外処理です。Javaではデフォルトの例外処理以外にエラーメールの送信、エラーログの生成、強制終了処理の実行といった任意の例外処理を付け加えることができます。

以下はJavaで例外処理を行う上で使用するキーワードです。

「例外をスローする」
Javaではエラーが発生した際、例外オブジェクトというエラー情報を保有したオブジェクトを生成し、そのオブジェクトをJava実行システムに渡します。この処理を「例外をスローする」と言います。
「例外ハンドラ」
エラーメールを送信する、エラーログを生成するなどの例外処理が記述された部分を「例外ハンドラ」と言います。
「例外をキャッチする」
Java実行システムが例外ハンドラを見つけることを 「例外をキャッチする」と言います。

【例1】デフォルトの例外処理の例です。

class ExException1{
    public static void main (String[] args) {
        int x = 10/0;  //0で除算
    }
}

実行結果1

D:\JAVA>javac ExException1.java

D:\JAVA>java ExException1
Exception in thread "main" java.lang.ArithmeticException: / by zero
      at ExException1.main(ExException1.java:3)  #デフォルトの例外処理

D:\JAVA>

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

class ExException2{
    public static void main (String[] args) {
        try {
            int x = 10/0;  //(1)0で除算
        //例外ハンドラ
        } catch (ArithmeticException e) {  //(2)
            System.out.println("0で除算はできません。");
        }
    }
}

解説2

  1. (1)整数を0で除算した場合に例外が発生し、例外オブジェクトが生成されJava実行システムに渡されます(例外をスローする)。
  2. (2) 例外がスローされるとJava実行システムは該当する例外ハンドラを捜します。該当する例外ハンドラを見つけたら(例外をキャッチする)、その例外ハンドラを実行します。例外ハンドラにはprintlnメソッドで「0で除算はできません。」を表示する処理が記載されています。

実行結果2

D:\JAVA>javac ExException2.java

D:\JAVA>java ExException2
0で除算はできません。   # 任意の例外処理

D:\JAVA>

例外の種類

例外が発生した際、例外オブジェクトが生成されることからもわかるように、Javaでは例外をクラスにより管理しています。すべての例外クラスはThrowableクラスの子孫クラスです。

例外の種類

例外関連のクラスは大きく分けて3つに分かれます。Errorクラス、RuntimeExceptionクラス、RuntimeExceptionクラス以外のExceptionクラスです。Errorクラスには例外処理では復旧できない種類の例外クラスが継承されています。OutOfMemory(メモリの不足)などです。RuntimeExceptionクラスにはJavaVMの内部で発生する例外クラスが継承されています。NullPointerException(Null参照を通してオブジェクトのメンバにアクセス)、ArithmeticException(整数を0で除算)などです。

Errorクラス、RuntimeExceptionクラスを継承する例外クラスにおいては任意の例外処理を記述することはあまり推奨されていません。それはこれらの例外クラスが単に典型的なプログラムを記述した際においてもその数は膨大なものとなり、任意の例外処理を記述するメリットを、例外処理を記述する煩雑さ、プログラムの見苦しさが上回ってしまうためです。これらのデメリットを上回るメリットがあるときのみ任意の例外処理を記述します。例外処理を記載しなくてもいい事からこれらの例外は非チェック例外と呼ばれています。

一方RuntimeException以外のExceptionクラスにおいては必ず任意の例外処理を記述しなければなりません。記述しない場合(デフォルトの例外処理の場合)はコンパイルエラーとなります。例外処理を必ず記載する必要があることからこれらの例外はチェック例外と呼ばれています。例外クラスとしてはFileNotFoundException(ファイルが見つからなかった場合)などがあります。

Exceptionクラスの子孫クラスはクラス名の最後に必ずExceptionが付きます。ErrorクラスとExceptionクラスの区別は容易に行えます。

【例3】チェック例外に対して、任意の例外処理を記載しない時の例です。

import java.io.*;

class ExException3 {
    public static void main (String[] args) {
        //チェック例外IOExceptionが発生する可能性がある処理
        FileWriter exFile = new FileWriter("exFile.txt");
    }
}

実行結果3

D:\JAVA>javac ExException3.java
ExException3.java:5: 例外 java.io.IOException は報告されません。スローするにはキ ャッチまたは、スロー宣言をしなければなりません。
   FileWriter exFile = new FileWriter("exFile.txt");
                ^
エラー 1 個   # 例外処理を記載していないため、コンパイルエラーが発生

D:\JAVA>

【例4】チェック例外に対して、任意の例外処理を記載した時の例です。

import java.io.*;

class ExException4 {
    public static void main (String[] args) {
        //任意の例外処理を記載
        try {
            FileWriter exFile = new FileWriter("exFile.txt");
        } catch(IOException e) {
            System.err.println(e.getMessage());
        }
    }
}

実行結果4

D:\JAVA>javac ExException4.java
                                                #例外処理を記載しているため、コンパイルエラーは発生しない
                                            D:\JAVA>

1はじめての例外