Developer

【はじめてのJava】例外を逃れる【例外処理編】
2021.09.30
Lv1

【はじめてのJava】例外を逃れる【例外処理編】

はじめてのJava

このシリーズでは、初めてJavaやプログラミングを勉強する方向けに、Javaによるプログラミングの基礎を説明していきます。
目標レベルは、Javaの資格試験の一つである「Oracle Certified Java Programmer, Silver」(通称Java Silver)に合格できる程度の知識の習得です。
はじめてJavaやプログラムに触れる方にもできるだけわかりやすい解説を心がけていきます。


例外の対応

前回の記事では、「try-with-resources文」を利用した、特殊な例外処理の方法を紹介しました。
今回は、例外に対処する方法の中でも「例外を逃れる」という方法を紹介していきます。

目次


例外を逃れる

以前にも紹介しましたが、例外処理が必須な例外が発生した際には、2つのパターンの対処方法があります。
「例外に対処する(その場で対処する)」と「例外を逃れる(別の箇所に例外処理を任せる)」の2つのパターンで例外を処理します。
今回は、「例外を逃れる(別の箇所に例外処理を任せる)」パターンを解説していきます。


throws

例外を逃れる(別の箇所に例外処理を任せる)」という記述は、メソッドを定義するときに「throws」キーワードを追加することで実現することができます。
以前の記事では、例外処理が必須な例外が発生した際には、try-catchという構文を利用して例外を処理しなければならないと説明しました。
しかし、今回の「throws」キーワードをメソッドの定義に追加することにより、例外処理を「そのメソッドの中ではなく、そのメソッドを呼び出した別の箇所」に任せるということが可能になります。
すなわち、「throws」キーワードをつけて定義されたメソッドを呼び出す際には、呼び出す処理を書く部分で例外処理のコードを書かなければならないということになります。

[構文]

アクセス修飾子 戻り値のデータ型 メソッド名( 引数 ) throws 例外クラス {
	//メソッドの中の処理;
}

実際に、使用例を挙げてthrowsの使い方を見てみましょう。

public class Sample{
    public static void main(String[] args){
    //test()メソッドを呼び出すときに、Exceptionクラスの例外クラスを処理しなければいけないので、
    //呼び出しているmainメソッド側でtry-catch句を利用して例外処理を行っている!
        try {
            test();
        }catch (Exception e) {
            e.printStackTrace();
        }
        
    }
    
    static void test() throws Exception{
        System.out.println("test");
    }
}

また、throwsの後に指定する例外クラスは、カンマ区切りで複数指定することができます。
その場合には、呼び出す側のクラスやメソッドで、throws句に指定された例外クラスのすべての例外クラスを処理する必要があります。


throwsとオーバーライド

throws句はメソッドにつけて定義することで、例外処理を別の箇所に任せることができました。
ここで、メソッドには「オーバーライド」という機能がありました。
オーバーライドは、クラスを継承した際にサブクラスの中でスーパークラスで定義されたメソッドの処理を書き換えるというものでした。
throwsキーワードが定義されたメソッドをオーバーライドする場合には注意しなければいけないことがあります。

  1. メソッドをオーバーライドするときに、スーパークラスのメソッドでthrows句が定義されている時、
    サブクラスのメソッドでthrowsで指定することができる例外クラスは、
    スーパークラスのthrows句に指定されている例外クラスと同じか、その例外クラスのサブクラスの例外クラスのみ

    class Super { 
        void test() throws IOException { //スーパークラスのthrows句に「IOExcepptin」を指定
        
        }
    }
    
    // OKなパターン①
    class Sub1 extends Super {
        @Override
        void test() throws IOException { 
         //サブクラスでスーパークラスと同じ「IOException」をthrows句に指定しているので問題なし    
        }
    }
    
    // OKなパターン②
    class Sub2 extends Super {
        @Override
        void test() throws FileNotFoundException { 
         //「FileNotFoundException」は「IOException」のサブクラスにあたるため問題なく指定できます。
        }
    }
    
    // NGなパターン
    class Sub3 extends Super {
        @Override
        void test() throws Exception {
         //「Exception」は「IOException」のスーパークラスにある例外クラスなので、コンパイルエラーになる。
        }
    }
    
  2. メソッドをオーバーライドするときに、サブクラスのメソッドのthrows句には「RuntimeException」または
    RuntimeExceptionのサブクラス」の例外クラスは、スーパークラスのメソッドにかかわらずthrowsに指定できる。

    class Super {
        void test() throws IOException { //スーパークラスのthrows句に「IOExcepptin」を指定
    
        }
    }
    
    // OKなパターン①
    class Sub1 extends Super {
        @Override
        void test() throws RuntimeException { 
         //「RuntimeException」はスーパークラスにかかわらず指定できる
        }
    }
    
    // OKなパターン②
    class Sub2 extends Super {
        @Override
        void test() throws NullPointerException { 
         //「NullPointerException」は「RuntimeException」のサブクラスなので、こちらもスーパークラスにかかわらず指定できる
        }
    }
    
    // NGなパターン
    class Sub3 extends Super {
        @Override
        void test() throws ClassNotFoundException { 
         //「ClassNotFoundException」は「IOException」のサブクラスでもなく、「RuntimeException」のサブクラスでもないので、指定するとコンパイルエラーになる
        }
    }
    
  3. スーパークラスのメソッドにthrows句が指定されていたとしても、オーバーライドしたメソッドにthrowsを記述しなくてもよい。

    class Super {
        void test() throws IOException { //スーパークラスのthrows句に「IOExcepptin」を指定
    
        }
    }
    
    class Sub1 extends Super {
        @Override
        void test() { //サブクラスでthrowsを書かなくてもOK
    
        }
    }
    

例外処理編・次回の内容

今回は例外を逃れる(別のクラスに任せる)方法を紹介しました。
次回は、意図的に例外を発生させる方法を解説していきます。


初めてのJavaシリーズの目次はこちら
例外処理編の記事一覧はこちら


java 11 の練習問題一覧はこちら
はじめてのJavaシリーズの練習問題一覧はこちら