「Javaの例外チェイン」の版間の差分

提供: Java入門
移動: 案内検索
(ページの作成:「Javaの例外チェイン(Chained Exception)とは、例外情報を伝播していくための機能です。1つ目の例外がスローされ、1つ目の例...」)
 
(相違点なし)

2015年9月19日 (土) 11:16時点における最新版

Javaの例外チェイン(Chained Exception)とは、例外情報を伝播していくための機能です。1つ目の例外がスローされ、1つ目の例外をキャッチしたあとに、さらに例外を投げていくときに、2つ目の例外の情報に1つ目の例外の情報を付加してスローします。このように、例外をキャッチするために、前の例外の情報を追加して、新しく例外を投げ続けていく場合に、最終的にエラー処理を実行するところに、エラーを伝搬する、といったことが可能になります。ここでは、例外チェインのスローの仕方を説明します。

読み方

例外チェイン
れいがい ちぇいん

概要

例外を受け取ったときに、新しい例外を送出(throw)したくなります。しかしながら、新しい例外でオリジナルの例外の情報を伝達したいときには、例外チェインで実現できます。

これは、簡単に実現できます。受け取った例外を新しい例外のコンストラクタにセットしてスローするだけです。

例外の情報を失う例 Exception1

まず最初に、例外チェインなしに、例外をキャッチしたときに、新しい例外を投げるコードを見てみましょう。

public class Exception1
{
        public static void main(String[] args) {
                try {
                        try {
                                throw new Exception("One"); // 1つ目の例外
                        } catch (Exception e) { // 1つ目のキャッチ
                                throw new Exception("Two"); // 2つ目の例外
                        }
                } catch (Exception e) { // 2つ目のcatch
                        e.printStackTrace();
                }
        }
}

上記のコードでは、1つ目の例外は、throwの直後のcatchによって受け取られます。その中で、さらにthrowをしています(2)。2つ目のキャッチでは、2回目の例外を受け取ります。

2回目のキャッチでは、2つ目の例外の情報しかないため、スタックトレースの結果は、以下の通りになります。

$ java Exception1
java.lang.Exception: Two
        at Exception1.main(Exception1.java:15)

このように、ただ、例外をキャッチして、新しく例外をスローしていると、例外の情報が伝達されず、結果的に、どこでなにが起きて、このエラーになったのか、分からなくなってしまうという問題があります。

例外チェインの簡単な例 Throwable1

前述した通り、例外チェインなしの例外処理では、例外の情報が失われるということがわかりました。

次に、例外チェインの例を見てみましょう。

ソースコード Throwable1.java

このコードは、例外チェインのためのサンプルです。

/*
 * Throwable1.java
 * Copyright (C) 2015 kaoru <kaoru@localhost>
 */
public class Throwable1
{
        public static void main(String[] args) {
                try {
                        try {
                                throw new Exception("One");	// 1つ目の例外
                        } catch (Exception e) {	// 1つ目のキャッチ
                                throw new Exception("Two", e);	// 2つ目の例外
                        }
                } catch (Exception e) {	// 2つ目のキャッチ
                        e.printStackTrace();
                }
        }
}

1つ目の例外を1つ目のキャッチで受け取っています。「2つ目の例外」をスローするときに、Exceptionクラスのコンストラクタの第2引数に、「1つ目の例外」の例外を渡します。これにより、1つ目の例外を2つ目の例外に情報を入れて、スローすることができます。これを例外チェインといいます。

コンパイル

javac Throwable1.java

実行例

例外チェインにより、1つ目の例では、内側の例外が2つ目のキャッチに情報が伝達されませんでしたが、2つ目の Throwable1.java のコードでは、1つ目の例外の情報も含めて、2つ目のキャッチまで情報が伝達されていることが、以下の実行結果のスタックトレースからわかります。

$ java Throwable1
java.lang.Exception: Two
        at Throwable1.main(Throwable1.java:12)
Caused by: java.lang.Exception: One
        at Throwable1.main(Throwable1.java:10)

例外チェインをSystem.out.printlnで表示した場合

public class Throwable1
{
        public static void main(String[] args) {
                try {
                        try {
                                throw new Exception("One");     // 1つ目の例外
                        } catch (Exception e) { // 1つ目のキャッチ
                                throw new Exception("Two", e);  // 2つ目の例外
                        }
                } catch (Exception e) { // 2つ目のキャッチ
                        e.printStackTrace();
                        System.out.println("------");
                        System.out.println(e);	// <--- ココ
                }
        }
}

最後のprintlnでは、最後の例外のメッセージだけが表示されます。

$ java Throwable1
java.lang.Exception: Two
        at Throwable1.main(Throwable1.java:12)
Caused by: java.lang.Exception: One
        at Throwable1.main(Throwable1.java:10)
------
java.lang.Exception: Two

短い例外チェインの例

少し短い例外チェインの例を見てみましょう。

ソースコード Throwable2.java

なにが違うかというと、2つ目の例外の引数が1つだけになっています。

/*
 * Throwable2.java
 * Copyright (C) 2015 kaoru <kaoru@localhost>
 */
public class Throwable2
{
        public static void main(String[] args) {
                try {
                        try {
                                throw new Exception("One");     // 1つ目の例外
                        } catch (Exception e) { // 1つ目のキャッチ
                                throw new Exception(e); // 2つ目の例外
                        }
                } catch (Exception e) { // 2つ目のキャッチ
                        e.printStackTrace();
                }
        }
}

コンパイル

javac Throwable2.java

実行例

このように、短い例外チェインの場合は、以下の様なスタックトレースになります。

$ java Throwable2
java.lang.Exception: java.lang.Exception: One
        at Throwable2.main(Throwable2.java:14)
Caused by: java.lang.Exception: One
        at Throwable2.main(Throwable2.java:12)

関連項目