カテゴリ: Java 更新日: 2026/05/23

JavaのThrowableクラスを初心者向けに完全解説!エラー処理の基本

Throwable
Throwable

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

生徒

「JavaのThrowableクラスって何ですか?」

先生

「Throwableクラスは、Javaの例外処理機構の基盤となるクラスで、エラーや例外を表現するために使われます。」

生徒

「エラーと例外の違いって何ですか?」

先生

「良い質問ですね。それについて詳しく説明していきます。Throwableクラスの仕組みも一緒に見てみましょう!」

1. Throwableクラスとは?

「1. Throwableクラスとは?」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

1. Throwableクラスとは?
1. Throwableクラスとは?

Javaでプログラムを動かしていると、入力ミスやネットワークの切断、メモリ不足など、さまざまな問題が発生することがあります。これらの「想定外の事態」をすべてまとめて管理しているのが、Throwable(スローアブル)クラスです。

名前の由来は、英語の「Throw(投げる)」と「able(〜できる)」を組み合わせたもので、「(エラーとして)投げることができる」という意味を持っています。Javaの世界では、何か問題が起きたときにこのThrowableオブジェクトが「ポイッ」と投げられ、それを私たちがキャッチして対処する仕組みになっています。

Throwableクラスは、大きく分けてエラー(Error)例外(Exception)の2つの子供(サブクラス)を持っています:

  • Throwable(すべての親)
    • Error:プログラムの外側で起きる、自分ではどうしようもない致命的な問題(例:パソコンのメモリが足りない)
    • Exception:プログラムの中で起きる、対処可能な問題(例:読み込むファイルが見つからない)

プログラミング未経験の方でもイメージしやすいように、簡単な「例外を投げる」サンプルコードを見てみましょう。ここでは、わざと例外を発生させて、それがThrowableとして扱われる様子を確認します。


public class ThrowableIntro {
    public static void main(String[] args) {
        try {
            // 「新しい例外」を作成して、わざと投げます
            Throwable myProblem = new Throwable("プログラムで何かが起きました!");
            throw myProblem;

        } catch (Throwable t) {
            // 投げられた問題(Throwable)をここでキャッチします
            System.out.println("キャッチした内容: " + t.getMessage());
        }
    }
}

このコードでは、new Throwableで問題の情報を詰め込んだ箱を作り、throwで投げ、catchで受け取っています。Throwableは、Javaにおける「トラブル対応の窓口」のような存在だと覚えておきましょう。

2. Throwableの主なメソッド

2. Throwableの主なメソッド
2. Throwableの主なメソッド

Throwableクラスには、エラーや例外の詳細を取得したり、スタックトレースを出力するための便利なメソッドが用意されています。以下が主なメソッドです:

  • getMessage(): エラーや例外のメッセージを取得
  • printStackTrace(): スタックトレース(エラー発生箇所)を表示
  • toString(): エラーや例外の簡単な説明を文字列で返す

以下はThrowableクラスを使った基本的な例です:


public class ThrowableExample {
    public static void main(String[] args) {
        try {
            throw new Exception("サンプルの例外です");
        } catch (Throwable t) {
            System.out.println("メッセージ: " + t.getMessage());
            t.printStackTrace();
        }
    }
}

3. Throwableを使うケース

3. Throwableを使うケース
3. Throwableを使うケース

通常の例外処理では、Exceptionまたはそのサブクラスをキャッチしますが、Throwableを直接キャッチすることも可能です。ただし、Errorをキャッチするのは推奨されません。Errorは通常、プログラムでは回復できない致命的な問題(例えばメモリ不足)を表します。

以下の例は、Throwableをキャッチしてエラーか例外かを判別するコードです:


public class ThrowableCatchExample {
    public static void main(String[] args) {
        try {
            throw new Exception("例外が発生しました");
        } catch (Throwable t) {
            if (t instanceof Error) {
                System.out.println("Error: " + t.getMessage());
            } else if (t instanceof Exception) {
                System.out.println("Exception: " + t.getMessage());
            }
        }
    }
}

4. Throwableを使用する際の注意点

「4. Throwableを使用する際の注意点」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

4. Throwableを使用する際の注意点
4. Throwableを使用する際の注意点

Throwableを直接扱うことは、通常のJavaプログラミングではあまり一般的ではありません。その理由は以下の通りです:

  • 回復不可能なErrorをキャッチしても、問題を解決できるとは限らない
  • 例外処理の意図が不明確になる可能性がある

したがって、特別な場合を除き、Exceptionやそのサブクラスを使用する方が適切です。

5. エラーと例外の違いを具体例で理解する

5. エラーと例外の違いを具体例で理解する
5. エラーと例外の違いを具体例で理解する

ErrorはJVMや実行環境の深刻な異常(OutOfMemoryErrorStackOverflowErrorなど)を表し、通常は復旧を試みません。一方、Exceptionはプログラム内で想定しうる異常(IOExceptionSQLExceptionなど)で、適切に処理・再試行・通知が可能です。

  • Error の例:メモリ不足、クラスロード失敗など(原則キャッチしない)
  • Exception の例:ファイル未存在、ネットワーク切断、形式不正など(状況に応じて処理)

// Errorは原則キャッチしない方針(例としてのアンチパターン)
try {
    // ここでJVM由来の重大なErrorが発生したとしても...
} catch (Error e) {
    // 問題の根本解決にならない可能性が高い
    System.err.println("致命的: " + e); 
    throw e; // 上位へ伝播させるのが基本
}

6. チェック例外と実行時例外(RuntimeException)の違い

6. チェック例外と実行時例外(RuntimeException)の違い
6. チェック例外と実行時例外(RuntimeException)の違い

チェック例外はメソッド宣言にthrowsが必要で、呼び出し側に対処を促す設計です。実行時例外RuntimeException)はプログラミング上のバグや事前条件違反を表し、throwsは不要です。


import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;

public class ReadSample {
    // チェック例外: 呼び出し側に対処(try-catch or throws)を強制
    public static String readFirstLine(Path path) throws IOException {
        try (BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
            return br.readLine();
        }
    }

    // 実行時例外: 事前条件(非null等)を満たさないと発生し得る
    public static int lengthOf(String s) {
        // sがnullならNullPointerException(実行時例外)
        return s.length();
    }
}
  • 外部要因(I/O、DB、ネットワーク)=チェック例外で通知し、リトライや代替処理を検討。
  • プログラミングミス(NullPointerException等)=実行時例外。入力検証やテストで防止。

7. 原因(Cause)と例外チェーン:ラップと再スローのベストプラクティス

「7. 原因(Cause)と例外チェーン:ラップと再スローのベストプラクティス」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

7. 原因(Cause)と例外チェーン:ラップと再スローのベストプラクティス
7. 原因(Cause)と例外チェーン:ラップと再スローのベストプラクティス

Throwableは「原因」を保持できます(getCause())。下位レイヤの例外を上位ドメインの文脈でラップして再スローすると、スタックトレースと意味の両方を保てます。


import java.sql.SQLException;

class UserRepository {
    void save(Object user) throws SQLException {
        throw new SQLException("DB接続に失敗");
    }
}

public class ServiceLayer {
    private final UserRepository repo = new UserRepository();

    public void register(Object user) {
        try {
            repo.save(user);
        } catch (SQLException e) {
            // ドメイン文脈を付与してラップ
            throw new IllegalStateException("ユーザー登録に失敗: 保存処理でエラー", e);
        }
    }

    public void rethrowExample() throws IOException {
        try {
            // I/O処理...
            throw new IOException("読み取り失敗");
        } catch (IOException e) {
            // ログ後にそのまま再スロー(スタックは保持)
            // Logger等で記録してから
            throw e;
        }
    }
}

古いAPIで原因を後付けする場合はinitCause()が使えます(ただし一度だけ)。ラップ時はメッセージにビジネス文脈を含め、causeで元例外を失わないようにしましょう。

8. try-with-resourcesとサプレッシド例外・スタックトレースの読み方

8. try-with-resourcesとサプレッシド例外・スタックトレースの読み方
8. try-with-resourcesとサプレッシド例外・スタックトレースの読み方

try-with-resourcesはリソースクローズ時の例外を「サプレッシド(抑制)例外」として保持します。getSuppressed()で補助情報を確認できます。スタックトレースは上から「直近の呼び出し」を読み、原因(getCause())へ辿るのがコツです。


import java.io.*;
import java.nio.file.*;
import java.nio.charset.StandardCharsets;

public class SuppressedDemo {
    public static void main(String[] args) {
        try {
            readAndFail(Paths.get("data.txt"));
        } catch (Exception ex) {
            System.err.println("主要な例外: " + ex);
            for (Throwable s : ex.getSuppressed()) {
                System.err.println("サプレッシド: " + s);
            }
            // 本番ではprintStackTrace()ではなくロガー出力が推奨
            ex.printStackTrace();
        }
    }

    static void readAndFail(Path p) throws Exception {
        try (BufferedReader br = Files.newBufferedReader(p, StandardCharsets.UTF_8)) {
            throw new RuntimeException("処理中に失敗");
        }
    }
}
  • 本番運用ではprintStackTrace()よりロガー(例:java.util.loggingやSLF4J)で記録。
  • fillInStackTrace()は重い処理のため多用しない(パフォーマンスに注意)。
  • スタックトレースは「発生箇所 → 呼び出し元」の順で上から読むと理解しやすい。

まとめ

まとめ
まとめ

JavaのThrowableクラスは、エラー処理の基本を支える非常に重要なクラスです。このクラスを理解することで、例外処理の仕組みや、ErrorExceptionの違いを正しく認識できるようになります。 Throwableを直接使用することは少ないものの、例外の基本構造を把握することは、安全で効果的なプログラミングに繋がります。

主に学んだポイントは次の通りです:

  • Throwableは、ErrorExceptionの共通の親クラスであること
  • Errorは通常、システムレベルの致命的な問題であり、回復は難しい
  • Exceptionはプログラム内で発生する例外であり、適切な処理で回復可能
  • Throwableの便利なメソッド(getMessage()printStackTrace()など)

以下は、まとめとしてThrowableを活用した例外のデバッグ例です:


public class ThrowableDebugExample {
    public static void main(String[] args) {
        try {
            causeError();
        } catch (Throwable t) {
            System.out.println("エラーの発生: " + t.toString());
            System.out.println("詳細なスタックトレース:");
            t.printStackTrace();
        }
    }

    private static void causeError() throws Exception {
        throw new Exception("意図的に発生させた例外");
    }
}

エラーの発生: java.lang.Exception: 意図的に発生させた例外
詳細なスタックトレース:
java.lang.Exception: 意図的に発生させた例外
    at ThrowableDebugExample.causeError(ThrowableDebugExample.java:9)
    at ThrowableDebugExample.main(ThrowableDebugExample.java:5)

このコードでは、例外が発生した際にThrowableの機能を活用し、エラーの詳細情報を出力しています。

先生と生徒の振り返り会話

生徒

「Throwableクラスの役割がだいぶ理解できました!けど、Errorをキャッチするのは本当にダメなんですね?」

先生

「そうですね。Errorはシステム全体に関わる致命的な問題なので、無理にキャッチしても解決にならないことがほとんどです。通常はExceptionだけをキャッチして適切に対処しましょう。」

生徒

「例外の詳細を出力するprintStackTrace()がとても便利そうです!」

先生

「その通りです。エラーの発生箇所や原因を特定するための強力なツールなので、デバッグ時にはぜひ活用してくださいね。」

この記事を読んだ人からの質問

「この記事を読んだ人からの質問」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

この記事を読んだ人からの質問
この記事を読んだ人からの質問

プログラミング初心者からのよくある疑問/質問を解決します

JavaのThrowableクラスとは何ですか?

Throwableクラスは、Javaの例外処理機構の基盤となるクラスで、エラー(Error)や例外(Exception)を表現するために使われます。すべてのエラーや例外はThrowableを継承しており、例外処理の基本を理解する上で重要なクラスです。

ErrorとExceptionの違いは何ですか?

Errorは、通常プログラムの回復が難しい致命的な問題(例えばメモリ不足やJVMのクラッシュ)を表します。一方、Exceptionはプログラム内で発生する例外であり、適切に処理すれば回復可能です。

Throwableクラスの主なメソッドには何がありますか?

主なメソッドには、エラーや例外のメッセージを取得するgetMessage()、スタックトレースを出力するprintStackTrace()、例外情報を文字列で取得するtoString()などがあります。

Throwableクラスを直接使うことはありますか?

通常のプログラムでは、Throwableを直接使うことは少なく、Exceptionやそのサブクラスを使って例外処理を行います。ただし、特定の状況ではThrowableをキャッチしてエラーと例外を区別することもあります。

printStackTrace()メソッドはどのようなときに使うべきですか?

printStackTrace()メソッドは、エラーや例外が発生したときに、その発生箇所や原因を特定するために使います。デバッグ時に非常に役立つメソッドで、例外の発生元を調べるのに便利です。

Throwableクラスを使うメリットは何ですか?

Throwableを使うことで、エラーや例外の詳細情報を取得できるため、デバッグやログ出力に役立ちます。また、ExceptionとErrorを区別する処理が可能になります。

try-catch文でThrowableをキャッチするのは問題がありますか?

基本的に、Throwableをキャッチするのは推奨されません。なぜなら、Errorをキャッチしても適切に処理できるとは限らないためです。通常はExceptionクラスをキャッチするのが適切です。

JavaではErrorをキャッチしないほうが良いのはなぜですか?

Errorはシステムレベルの深刻な問題を表しており、通常のプログラムでは回復が難しいため、無理にキャッチすることは推奨されません。適切な例外処理を行うためには、Exceptionのみをキャッチする方が良いでしょう。

Throwableを継承した独自の例外クラスを作成できますか?

はい、可能ですが、通常はExceptionまたはRuntimeExceptionを継承した独自の例外クラスを作成するのが一般的です。Throwableを直接継承することは稀です。

Javaの例外処理において、チェック例外と非チェック例外の違いは何ですか?

チェック例外(Checked Exception)は、コンパイル時に処理が強制される例外で、IOExceptionなどが該当します。一方、非チェック例外(Unchecked Exception)は、RuntimeExceptionを継承する例外であり、コンパイル時に処理が強制されません。NullPointerExceptionなどが該当します。

Errorが発生した場合、アプリケーションはどのように振る舞うべきですか?

基本は「Fail-Fast」です。重大障害を検知したら速やかにログと監視通知を行い、プロセスを安全に停止します。無理に継続するとデータ破損や更なる不整合を招くため避けます。

Exceptionでも致命的と判断して停止すべきケースはありますか?

ドメイン整合性が失われた場合や、代替手段が無く継続で被害が拡大する場合は停止すべきです。例:トランザクション不整合、暗号鍵の読み込み失敗など。

ネットワーク障害はErrorですか、それともExceptionですか?

通常はException(例:IOException、SocketTimeoutException)として扱います。リトライやフォールバック、サーキットブレーカーなどの回復策を検討します。
カテゴリの一覧へ
新着記事
New1
Java
JavaのNotSerializableExceptionを完全解説!初心者でも理解できるシリアライズと例外処理
新規投稿
New2
Spring
Springの@Repositoryアノテーションの使い方を徹底解説!初心者でもわかるSpringフレームワークのデータアクセス
更新記事
New3
Spring
Springの@Componentアノテーションの使い方を徹底解説!初心者でもわかるSpring Boot入門
更新記事
New4
Java
Javaのjava.mathとBigIntegerのintValueメソッドを完全解説!初心者でもわかる数値変換の基本
更新記事
人気記事
No.1
Java&Spring記事人気No1
Servlet
JavaのHttpSessionを徹底解説!初心者でもわかるセッション管理の基本
No.2
Java&Spring記事人気No2
JSP
JSPの基本タグ一覧と使い方まとめ!実務で使えるタグを紹介
No.3
Java&Spring記事人気No3
JSP
JSPでフォームを表示して入力を受け取る基本手順をやさしく解説!初心者向けフォーム処理の入門ガイド
No.4
Java&Spring記事人気No4
Spring
Springの@Serviceアノテーションの使い方を徹底解説!初心者でもわかるSpring フレームワーク入門
No.5
Java&Spring記事人気No5
JSP
JSPでCSSやJSを読み込む基本!外部ファイルのパス指定に注意しよう
No.6
Java&Spring記事人気No6
Spring
Spring BootとJavaの互換性一覧!3.5/3.4/3.3はJava 21・17に対応してる?
No.7
Java&Spring記事人気No7
Spring
Spring Data JPA入門!findAll()やfindBy**()の使い方などデータベース操作の基礎を学ぶ
No.8
Java&Spring記事人気No8
JSP
JSPでif文・for文を使う方法!初心者でもわかるJavaとの違いと使い方