例外処理 (throw、throws)


前回は、例外処理 のうち try , catch , finally についてみました。今回は残りの例外処理についてみていきます。

例外の流れ

JavaマニュアルのThrowable クラスの説明に例外の流れの説明が書かれていたので引用します。

Throwable クラスは、Java 言語のすべてのエラーと例外のスーパークラスです。このクラス (またはそのサブクラスの内の 1 つ) のインスタンスであるオブジェクトだけが Java 仮想マシンによってスローされるか、Java の throw 構文によってスローされます。同じように、このクラスまたはそのサブクラスの内の 1 つだけが catch 節の引数の型に指定できます
通常、Error および Exception の 2 つのサブクラスのインスタンスは例外的な状況が発生したことを示すために使用されます。これらのインスタンスは、通常、関連する情報 (スタックトレースデータなど) を格納するために、例外的な状況に応じて新しく作成されます
スロー可能オブジェクトには、作成時のそのスレッドの実行スタックのスナップショットが含まれます。このクラスには、エラーについての詳細 な情報を示すメッセージ文字列も含まれます

Javaマニュアル参考・引用

例外が発生すると、エラーについての情報を含む例外オブジェクトが新しく作られます。この例外オブジェクトはJava仮想マシンに渡され、この渡す処理を「例外をスローする」といいます。Java仮想マシンは、作られた例外オブジェクトのクラスと一致する引数の型のcatch節を探し、該当があれば処理をします。この処理を「例外をキャッチする」といいます。

流れをまとめると次のようになります。

例外発生 → 例外オブジェクト生成 → 例外のスロー → 例外のキャッチ

throw

通常は例外的な状況が発生したときに例外処理が行われますが、意図的に例外を発生させ例外処理を行ってみます。

【例1】

public class Sample{
    public static void main(String[] args) {
        try{
            ArithmeticException error
                  = new ArithmeticException();
            throw error;
        }
        catch (Exception e){
            System.out.println("例外処理");
        }
    }
}
例外処理

例外の流れとして、まず例外オブジェクトが生成される必要があります。そこで意図的に例外を発生させる為に例外オブジェクトを作ります。例外オブジェクトはThrowable クラス自体かそのサブクラスである必要があるので、例1では代表としてArithmeticExceptionクラスで例外オブジェクトを作りました。

            ArithmeticException error
                  = new ArithmeticException();

次に例外をスローする必要があります。意図的に作成した例外オブジェクトは自動的にスローされません。そこで「throw」キーワードを使って意図的に例外をスローします。

             throw error;

Java仮想マシンに例外をスローすると例外のキャッチは自動的にしてくれます。例1の結果からcatch節の処理がされていることがわかります。

throws

try節の処理に別のインスタンスのメソッドを実行させ、そのメソッドで例外が起こったときの処理をみていきます。

【例2】

public class ThrowsSample{
    void errorMethod () {
        ClassNotFoundException error
              = new ClassNotFoundException();
        throw error;
    }
}
public class Sample{
    public static void main(String[] args) {
        ThrowsSample obj = new ThrowsSample();
        try{
            obj.errorMethod();
        }
        catch (Exception e){
            System.out.println("例外処理");
        }
    }
}
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
処理されない例外の型 ClassNotFoundException

Sampleクラスの5行目でThrowsSamplクラスのerrorMethodメソッド参照しています。errorMethodメソッドでは例外オブジェクトをつくり例外をスローしています。try節にあるのでcatch節の処理がされそうですが結果はエラーになります。
理由は例外が発生したメソッド内で例外処理をしようとするので、errorMethodメソッドで例外が発生したならばerrorMethodメソッド内に「try~catch」を書く必要があります。
しかし例外が発生しそうなメソッド全てに「try~catch」を書くのも面倒ですし、例外処理をまとめてしたいときもあります。そこで例外オブジェクトを呼び出し元のメソッドにスローして、呼び出し元で例外処理を行うことができます。

例外オブジェクトを呼び出し元まにスローするには「throws」キーワードを使います。「throws」キーワードを省略できる例外クラスもありますが、それはまた別の記事で説明しようと思います。

返却値の型 メソッド名(...) throws 例外クラス名1,例外クラス名2 {

呼び出し元へスローする例外クラスの指定はカンマ区切りで複数指定できます。
ではThrowsSampleクラスを「throws」キーワードを使って修正します。

public class ThrowsSample{
    void errorMethod () throws ClassNotFoundException{
        ClassNotFoundException error
             = new ClassNotFoundException();
        throw error;
    }
}
例外処理

「throws ClassNotFoundException」を追加して、例外が発生した場合に呼び出し元へ例外オブジェクトをスローすることを指示しました。これで呼び出し元のSampleクラスに例外オブジェクトがスローされ、Sampleクラスには「try~catch」があるので例外処理が行われています。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です