[PR] 迷惑メール トップページプロ3ゼミJavaJava入門講座三学期単位12 →4時間目

4時間目 例外クラスを作っちゃおう

12−4−1.新たな例外クラスの作成方法

 例外クラスもクラスですから、新たに作成する事ができます。
例外クラスを新たに作成する事により、例外が起きた場合にも分かり易いように設計したり出来る為、プロジェ クトごとに新たに作成される事が多いようです。

 例外クラスを新たに作成してみましょう。
構文で表すと以下のようになります。
アクセス修飾子 class クラス名 extends Exception {
    :
    :
}
「Exception」クラスを継承しているクラスを継承していないと例外の機能を果たせません。

では、単位12 3時間目 スローして流すの「Sample12_3_1.java」をさらに改造し てみましょう。
MyException.java
package first.java.unit11.exception;

// 新たな例外クラス
public class MyException extends Exception {

    private String      data1;  // 数値1
    private String      data2;  // 数値2
    private StackTraceElement[] traces; // 問題行数

    // コンストラクタ
    public MyException(final String data1, final String data2,
            final StackTraceElement[] traces) {

        this.data1 = data1;
        this.data2 = data2;
        this.traces = traces;
    }

    // エラーを出力
    public void viewError() {

        if (data2 == null) {
            // 数値1でエラーが起きた場合
            System.err.println("数値1には" + data1 + "が入力されました");
            System.err.println("数値を入力して下さい");
        } else if (data2.equals("0")) {
            // 数値2が0の場合
            System.err.println("0では割り切れません。0以外の数値を入力して下さい");
        } else if (data2 != null) {
            // 数値2が0以外でエラーが起きた場合
            System.err.println("数値2には" + data2 + "が入力されました");
            System.err.println("数値を入力して下さい");
        }
        // 問題のある行数を出力する
        for (int i = 0; i < traces.length; i++) {
            if (traces[i].getLineNumber() != -1) {
                // 作成したソースの場合
                System.err.println(traces[i]);
            }
        }
    }
}
      

 新たに作成した例外クラス(MyException.java)から見て行きましょう。
「StackTraceElement[]」が気になると思いますが、これは間違えた行数の情報を保持するクラスです。
出力する箇所をクローズアップすると、
// 問題のある行数を出力する
for (int i = 0; i < traces.length; i++) {
    if (traces[i].getLineNumber() != -1) {
        // 作成したソースの場合
        System.err.println(traces[i]);
    }
}
です。
「traces[i].getLineNumber()」は、問題の有る行数だけを返すのですが、「-1」はソースが無い場合に返され ます。
ソースがある情報を出力する場合は「-1」以外を出力すればいいと言う事です。

Sample12_4_1.java
package first.java.unit12.sample;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import first.java.unit11.exception.MyException;

// 単位12 4時間目 サンプル1
public class Sample12_4_1 {

    // ここからスタート
    public static void main(final String[] args) {

        final ExceptionSample es = new ExceptionSample();
        try {
            System.out.println(es.view());
        } catch (final MyException e) {
            e.viewError();
        } finally {
            System.out.println("finallyブロック");
        }
    }
}

//
class ExceptionSample {

    public int view() throws MyException {

        BufferedReader br = null;
        String strData1 = null;
        String strData2 = null;
        int sum;

        try {
            br = new BufferedReader(new InputStreamReader(System.in));

            System.out.print("数値1ー>");
            strData1 = br.readLine();
            final int data1 = Integer.parseInt(strData1);
            System.out.print("数値2ー>");
            strData2 = br.readLine();
            final int data2 = Integer.parseInt(strData2);

            sum = data1 / data2;
        } catch (final ArithmeticException e) {
            throw new MyException(strData1, strData2, e.getStackTrace()); // 例外を発生させる
        } catch (final NumberFormatException e) {
            throw new MyException(strData1, strData2, e.getStackTrace()); // 例外を発生させる
        } catch (final IOException e) {
            throw new MyException(strData1, strData2, e.getStackTrace()); // 例外を発生させる
        } finally {
            try {
                if (br != null) {
                    // ストリームのクローズ
                    br.close();
                }
            } catch (final IOException e) {
                e.printStackTrace();
            }
        }

        return sum;
    }
}
      
数値1ー>10
数値2ー>5
2
finallyブロック

数値1ー>a
finallyブロック
数値1にはaが入力されました
数値を入力して下さい
first.java.unit12.sample.ExceptionSample.view(Sample12_4_1.java:42)
first.java.unit12.sample.Sample12_4_1.main(Sample12_4_1.java:18)

数値1ー>10
数値2ー>a
finallyブロック
数値2にはaが入力されました
数値を入力して下さい
first.java.unit12.sample.ExceptionSample.view(Sample12_4_1.java:45)
first.java.unit12.sample.Sample12_4_1.main(Sample12_4_1.java:18)

数値1ー>10
数値2ー>0
0では割り切れません。0以外の数値を入力して下さい
first.java.unit12.sample.ExceptionSample.view(Sample12_4_1.java:47)
first.java.unit12.sample.Sample12_4_1.main(Sample12_4_1.java:18)
finallyブロック
      

 新たな例外クラスを作成し、それを使って呼び出し元に例外を返しているので「throws」するのは 「MyException」だけ記述すればよい事になります。
例外が発生した場合は、「MyException」のコンストラクタに、「数値1」、「数値2」及び「問題あるソース行」 を渡しています。
「数値1」及び「数値2」を渡す為に、宣言をtryブロックの外にしています。
「BufferedReader」が今までとは違う対応がある事気づきましたか?
} finally {
    try {
        if (br != null) {
            // ストリームのクローズ
            br.close();
        }
    } catch (final IOException e) {
        e.printStackTrace();
    }
}
の部分ですが、これは後処理です。
後で習う「ストリーム」には、使用後に「クローズ」を必ず行わないといけないのですが、その為にfinallyブ ロックに記述します。
ここで注意するのは、「BufferedReader」の変数が「null」でない事を確認する必要があります。
「null」でクローズすると「NullPointerException」が発生します。
「NullPointerException」を発生させないために、チェックしています。

3時間目 スローして流すに戻る     単位13 スレッドに進む

単位12 例外処理を使おうに戻る

トップページに戻る