カテゴリ: Javaの例外処理 更新日: 2025/12/27

Javaの例外を連鎖的に処理する方法!causeとsuppressedの使い方を徹底解説

357
Java の例外を連鎖的に処理する(cause と suppressed)

先生と生徒の会話形式で理解しよう

生徒

「Javaの例外処理で、複数のエラーが関係してるときって、どうやって原因をたどればいいんですか?」

先生

「良いポイントですね。Javaではcausesuppressedという仕組みを使って、例外を連鎖的に扱えます。」

生徒

「連鎖的って、例外が例外を引き起こすってことですか?」

先生

「そのとおり!それでは、Javaの例外のcausesuppressedの使い方を詳しく見ていきましょう!」

1. Javaの例外処理とは?

1. Javaの例外処理とは?
1. Javaの例外処理とは?

Javaの例外処理は、プログラム中に発生するエラーをキャッチして、適切に処理するための仕組みです。基本的にはtrycatchfinallyを使って記述します。たとえばファイル読み込み処理やネットワーク通信、数値計算などで問題が発生したときに、例外を使って安全にプログラムの異常を扱います。

しかし現実のプログラムでは、単一の原因で例外が発生するとは限らず、ある例外が別の例外の原因になっていたり、複数の例外が関係することもあります。そんなときに役立つのがcausesuppressedという仕組みです。

2. 例外を連鎖的に追跡する「cause」プロパティ

2. 例外を連鎖的に追跡する「cause」プロパティ
2. 例外を連鎖的に追跡する「cause」プロパティ

causeは、ある例外が発生したときに「もともとの原因となった例外」を保持するためのプロパティです。これはThrowableクラスのgetCause()メソッドで取得できます。

例えば、ファイルの読み込み中にIOExceptionが発生し、それをラップしてRuntimeExceptionを投げたい場合、causeを使って例外の原因を関連づけることができます。


public class CauseExample {
    public static void main(String[] args) {
        try {
            try {
                throw new IllegalArgumentException("元の例外です");
            } catch (IllegalArgumentException e) {
                throw new RuntimeException("ラップされた例外です", e);
            }
        } catch (RuntimeException e) {
            System.out.println("メッセージ: " + e.getMessage());
            System.out.println("原因: " + e.getCause());
        }
    }
}

メッセージ: ラップされた例外です
原因: java.lang.IllegalArgumentException: 元の例外です

このように、causeを使うことで、最終的にどのようなエラーが何に起因していたのかをたどることができます。

3. 例外を補足して記録する「suppressed」プロパティ

3. 例外を補足して記録する「suppressed」プロパティ
3. 例外を補足して記録する「suppressed」プロパティ

suppressedは、主にtry-with-resources構文の中で使われます。複数のリソースを自動でクローズする際に、最初の例外を保持しつつ、他の例外も「抑制された(suppressed)」形で記録する仕組みです。

以下のようなコードで、リソースのクローズ時に複数の例外が出た場合に確認できます。


class MyResource implements AutoCloseable {
    private String name;
    MyResource(String name) { this.name = name; }

    @Override
    public void close() throws Exception {
        throw new Exception(name + "を閉じるときに例外発生");
    }
}

public class SuppressedExample {
    public static void main(String[] args) throws Exception {
        try (MyResource res1 = new MyResource("リソース1");
             MyResource res2 = new MyResource("リソース2")) {
            throw new Exception("処理中に例外発生");
        } catch (Exception e) {
            System.out.println("メインの例外: " + e.getMessage());
            for (Throwable suppressed : e.getSuppressed()) {
                System.out.println("抑制された例外: " + suppressed.getMessage());
            }
        }
    }
}

メインの例外: 処理中に例外発生
抑制された例外: リソース2を閉じるときに例外発生
抑制された例外: リソース1を閉じるときに例外発生

getSuppressed()メソッドで、クローズ処理などで発生した副次的な例外をすべて取得できます。

4. try-with-resources構文とsuppressedの関係

4. try-with-resources構文とsuppressedの関係
4. try-with-resources構文とsuppressedの関係

try-with-resourcesは、AutoCloseableインターフェースを実装したリソースを、自動でクローズしてくれる構文です。複数のリソースがある場合でも、クローズの順番に従って例外を適切に処理します。

例えば、ファイル、DB接続、ネットワークリソースなどを一度に扱う場合でも、安全にリソースを解放できます。その際、1つの例外をスローしつつ、それ以外の例外をsuppressedとして記録するのが、この構文の強みです。

5. causeとsuppressedの違いと使い分け

5. causeとsuppressedの違いと使い分け
5. causeとsuppressedの違いと使い分け
  • cause: ある例外が他の例外によって引き起こされたときの「原因」を表す。
  • suppressed: 主な例外の陰に隠れた、同時発生した他の例外を保持。

causeは基本的に「ラップ」する形式で使われますが、suppressedtry-with-resourcesなどの自動クローズ時に「副次的な例外」を記録するために使われます。

6. Java例外のデバッグ時に知っておきたいポイント

6. Java例外のデバッグ時に知っておきたいポイント
6. Java例外のデバッグ時に知っておきたいポイント

Javaでエラーや例外の原因を正確に追跡するためには、getCause()getSuppressed()を活用することが非常に重要です。IDE(IntelliJ IDEAやEclipse)でスタックトレースを確認するときも、原因のチェーンや抑制された例外が表示されるため、デバッグがしやすくなります。

また、ログ出力やエラーレポートの中でも、causesuppressedをログに含めておくことで、運用中の不具合をスムーズに調査できるようになります。

7. suppressedを手動で追加する方法

7. suppressedを手動で追加する方法
7. suppressedを手動で追加する方法

addSuppressed()メソッドを使えば、自分でThrowableに抑制された例外を追加することもできます。これはカスタムエラーハンドリングなどで便利です。


public class AddSuppressedExample {
    public static void main(String[] args) {
        Exception main = new Exception("メインの例外");
        Exception sub = new Exception("補足された例外");

        main.addSuppressed(sub);

        for (Throwable t : main.getSuppressed()) {
            System.out.println("抑制された: " + t.getMessage());
        }
    }
}

抑制された: 補足された例外
Javaの例外処理の一覧へ
新着記事
IAM Identity Centerの許可セットとポリシーの関係を解説
IAM Identity Centerの許可セットとポリシーの関係を初心者向けにわかりやすく解説!
Java の正規表現で「数字」や「英字」だけをチェックする方法
Javaの正規表現で「数字」や「英字」だけをチェックする方法を初心者向けに完全解説
Java で正規表現を使う方法(Pattern クラスと Matcher クラス)
Javaで正規表現を使う方法を完全解説!PatternクラスとMatcherクラスを初心者向けにやさしく説明
FlutterでQRコードの生成・読み取りをする方法
FlutterでQRコードの生成・読み取りを実装する方法!初心者でもできるQRアプリ開発
人気記事
インスタンスタイプの料金比較と最適な選び方(最新2025年版)
AWSのインスタンスタイプの料金比較と最適な選び方【2025年最新版】
【AWS】VPCの料金体系まとめ!無料枠・通信費・各種サービスごとの料金を徹底解説
【AWS】VPCの料金体系まとめ!無料枠・通信費・各種サービスごとの料金を徹底解説
【AWS】VPCエンドポイントとは?種類・使い方・S3連携まで完全解説
【AWS】VPCエンドポイントとは?種類・使い方・S3連携まで完全解説
【AWS】s3 cpコマンド完全ガイド!基本・recursive・exclude/includeも解説
【AWS】s3 cpコマンド完全ガイド!基本・recursive・exclude/includeも解説