カテゴリ: 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()メソッドで、クローズ処理などで発生した副次的な例外をすべて取得できます。

Javaをこれから始める人や、 オブジェクト指向の考え方を基礎から理解したい人には、 定番の入門書がこちらです。

スッキリわかるJava入門 第4版をAmazonで見る

※ Amazon広告リンク

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の例外処理の一覧へ
新着記事
Java
Java のカプセル化とは?データを安全に管理する仕組み
Java のカプセル化とは?データを安全に管理する仕組みを解説
Java
Java の継承の制約(final クラスや final メソッドの扱い)
Java の継承の制約を完全解説!final クラスや final メソッドの扱いを初心者向けにやさしく解説
AWS
【AWS】CLIで環境変数を使った安全な認証情報管理
【AWS CLI】環境変数で安全に認証情報を管理する方法を徹底解説!初心者向けセキュリティ対策ガイド
Java
Java のコンストラクタと継承(親クラスのコンストラクタを呼ぶ方法)
Java のコンストラクタと継承(親クラスのコンストラクタを呼ぶ方法)を初心者向けにやさしく解説
人気記事
AWS
【AWS】s3 cpコマンド完全ガイド!基本・recursive・exclude/includeも解説
【AWS】s3 cpコマンド完全ガイド!基本・recursive・exclude/includeも解説
AWS
【AWS】VPCエンドポイントとは?種類・使い方・S3連携まで完全解説
【AWS】VPCエンドポイントとは?種類・使い方・S3連携まで完全解説
AWS
インスタンスタイプの料金比較と最適な選び方(最新2026年版)
AWSインスタンスタイプの料金比較と最適な選び方!初心者でもわかる2025年最新ガイド
AWS
【AWS】RDSの料金体系まとめ!ざっくり理解・高いと感じる理由も解説
【AWS】RDSの料金体系まとめ!ざっくり理解・高いと感じる理由も解説

🔌 USBポート不足を解消

Type-C 1本で拡張。
開発・作業環境を一気に快適に

UGREEN USB-Cハブを見る

※ Amazon広告リンク