未来エンジニア養成所Blog

プログラミングを皆に楽しんでもらうための情報をお届けします。

【Java】例外処理 Part3

title

前回に引き続き例外処理の解説をします。

前回の記事はこちら phoeducation.work

phoeducation.work


独自に例外クラスを作成する方法

これまでは例外が発生したときJavaに用意されている例外クラスに処理を任せていましたが、エラーが発生したときに独自の処理を行うこともできます。

独自の例外処理を行うには、具体的な例外処理を記述したオリジナルの例外クラスを作成します。

オリジナルの例外クラスを作成する手順は次の通りです。

  1. Exceptionクラスを継承したオリジナルの例外クラスを作成する
  2. 例外が発生する可能性があるメソッドにthrows宣言をする
      戻り値 メソッド名(引数リスト) throws オリジナル例外クラス名
  3. 例外が発生しそうなメソッドの呼び出し元クラスのクラスでthrowを記述して、例外オブジェクトを作成する
      throw オリジナル例外クラス名
  4. オリジナルの例外がスローされた場合の例外処理を記述する


【独自の例外クラス】

public class ExceptionSample08 {
    public static void main(String[]args){
        MyCheck obj = new MyCheck();
        try{
            obj.check(10);
            obj.check(-10);
        }catch(MyError e){
            System.out.println(e. message);
        }
    }
}
class MyCheck{
    public void check(int age) throws MyError{
        if(age < 0){
            MyError e = new MyError();
            throw e;
        }else{
            System.out.println("正常に終了しました");
        }
    }
}
class MyError extends Exception{
    String message = "MyError例外が発生しました";
}


実行結果

正常に終了しました
MyError例外が発生しました


22行目にMyErrorというオリジナルの例外クラスを、Exceptionクラスを継承して作成しています。

12行目からのMyCheckクラスではcheck()メソッドにthrows MyErrorをつけて定義し、このメソッドはMyError例外が発生すると宣言しておきます。

メソッドの処理内で引数に与えられた値が0より小さい場合は、MyEerrorクラスのオブジェクトを生成して、MyErrorクラスのオブジェクトeにエラーメッセージが格納されたString型の変数messageが生成されます。

throw eとすることで、実際に例外オブジェクトを呼び出し元のmain()メソッドに投げます。

main()メソッドの7行目のcatchブロックでそれを受け取り、「MyError例外が発生しました」と出力をします。

例外


rethrow(再スロー)
1つのアプリケーション内で複数のクラスを使用するような場合、スローされた例外オブジェクトをcatchブロックでいったん受け取った後、異なる例外クラスに変更してスローすることをrethrow(再スロー)と言います。

これはJDK7からの機能です。


rethrow(再スロー)

public class ExceptionSample09 {
    public static void main(String[] args) {
        try{
            method(-10);
            method(10);
        }catch(MyExceptionA e){
            System.out.println(e.msgA);
        }catch(MyExceptionB e){
            System.out.println(e.msgB);
        }
    }
    public static void method(int age) throws MyExceptionA, MyExceptionB{
        try{
            if(age < 0){
                throw new MyExceptionA();
            }else{
                throw new MyExceptionB();
            }
        }catch(Exception e){
            throw e;
        }
    }
}
class MyExceptionA extends Exception{
    String msgA = "MyExceptionA";
}
class MyExceptionB extends Exception{
    String msgB = "MyExceptionB";
}


実行結果

MyExceptionA


4行目をコメントにして再度実行します。

MyExceptionB


24行目~29行目で2つの独自の例外クラスを定義しています。

12行目からのmethod()メソッドの定義ではageの値によって発生させる例外を振り分けています。

通常なら19行目のcatchブロックでは、2つの例外クラスをマルチcatchで記述するか、もしくはcatchブロックをそれぞれ記述しなければなりません。

JDK7からはここで、Exceptionクラスでいったん受け取って、その後、それぞれの例外クラスに再スローすることができます。


メソッドのオーバーライドの注意点

クラスを継承する際にスーパークラスで定義したメソッドをサブクラスでオーバーライドすることができます。

スーパークラスのメソッドで例外がスローされている場合、サブクラスでそのメソッドをオーバーライドする際には、例外の指定に注意が必要です。

  • サブクラスのメソッドで例外をスローする場合、スーパークラスのメソッドがスローする例外と同じか、その例外のサブクラスとする
  • スーパークラスのメソッドが例外をスローしていても、サブクラスのメソッドで例外をスローしないようにできる
  • RuntimeExceptionとRuntimeExceptionのサブクラスの例外は、スーパークラスのメソッドの例外に関係なくスローできる


【メソッドオーバーライド時の例外の指定】

import java.io.FileNotFoundException;
import java.io.IOException;
public class ExceptionSample10 {
    public static void main(String args[]){
        Super obj = new Sub();
        try{
            obj.method1();
            obj.method2();
            obj.method3();
            obj.method4();
        }catch(Exception e){}
    }
}
class Super{
    void method1() throws IOException{
        System.out.println("スーパークラスのmethod1");
    }
    void method2() throws ClassNotFoundException{
        System.out.println("スーパークラスのmethod2");
    }
    void method3() throws ClassNotFoundException{
        System.out.println("スーパークラスのmethod3");
    }
    void method4() throws ClassNotFoundException{
        System.out.println("スーパークラスのmethod4");
    }
}
class Sub extends Super{
    void method1() throws FileNotFoundException{
        System.out.println("サブクラスのmethod1");
    }
    //void method2() throws Exception{
    // System.out.println("サブクラスのmethod2");
    //}
    void method3(){
        System.out.println("サブクラスのmethod3");
    }
    void method4() throws NullPointerException{
        System.out.println("サブクラスのmethod4");
    }
}
class Super{
    void method1() throws IOException{
        System.out.println("スーパークラスのmethod1");
    }
    void method2() throws ClassNotFoundException{
        System.out.println("スーパークラスのmethod2");
    }
    void method3() throws ClassNotFoundException{
        System.out.println("スーパークラスのmethod3");
    }
    void method4() throws ClassNotFoundException{
        System.out.println("スーパークラスのmethod4");
    }
}
class Sub extends Super{
    void method1() throws FileNotFoundException{
        System.out.println("サブクラスのmethod1");
    }
    //void method2() throws Exception{
    // System.out.println("サブクラスのmethod2");
    //}
    void method3(){
        System.out.println("サブクラスのmethod3");
    }
    void method4() throws NullPointerException{
        System.out.println("サブクラスのmethod4");
    }
}


実行結果

サブクラスのmethod1
スーパークラスのmethod2
サブクラスのmethod3
サブクラスのmethod4


32~34行のコメントをはずすと、コンパイルエラーになります。

error


Superクラスで定義したmethod1、method2、method3、method4をSubクラスでオーバーライドしています。

スーパークラスとサブクラスのメソッドの例外処理は以下の関係になっています。

例外処理の関係

継承関係


まとめ

  • 例外処理

    • 実行時に発生するエラーで、例外が発生することを「例外がスローされる」といいます。
    • プログラム実行中にエラーが発生した場合の対処方法を記述することを「例外処理」といいます。
    • 例外が発生した場合、何もしないとプログラムがそこで終了してしまうので、エラーメッセージを表示するなどして、プログラムを続行できるようにします。
    • try-catch-finally構文もしくはthrowsキーワードを使用します。
  • 例外の種類

    • Errorクラスとそのサブクラス(非チェック例外)。
    • RuntimeExceptionクラスとそのサブクラス(非チェック例外)。
    • RuntimeExceptionクラス以外のExceptionのサブクラス(チェック例外)。
  • 例外の活用

    • 複数のcatchブロックを定義できます。
    • 継承関係にない例外クラスを1つのcatchブロックにまとめることができます。
    • 独自に例外クラスを作成することができます。
    • throwsキーワードによる例外処理では、メソッドのオーバーライドに注意します。


参考図書



独学で挫折しそうになったら、オンラインプログラミングスクール
未来エンジニア養成所Logo



あわせて学習したい

phoeducation.work phoeducation.work