CodeGym /コース /JAVA 25 SELF /Java における例外の階層

Java における例外の階層

JAVA 25 SELF
レベル 24, レッスン 0
使用可能

1. クラス Throwable: すべての例外の祖先

ここでは、Java の例外システムの仕組みを詳しく見ていきます。Throwable とは何か、Exception と Error の違い、そして「検査例外」と「非検査例外」とは何か。これは、プログラムで適切にエラー処理を行うための基礎です。

Java ではすべての例外とエラーは、java.lang.Throwable クラスを継承するオブジェクトです。
Throwable は、Java における問題処理の階層全体の祖となる存在です。

概略:

Throwable
├── Exception
└── Error

Throwable は、Java で「throw」でき「catch」できるすべてのものの基底クラスです。直接使用するものではなく、より具体的なエラー型のための土台として機能します。

Exception — 「通常の」エラー向け

Exception は、プログラム内で発生しうる、そして処理すべき例外の基底クラスです。これは「業務的な」エラーで、ファイル、ネットワーク、入出力、ユーザーの操作ミスなどに起因します。多くの try-catch は Exception のサブクラスを扱うことになります。

例:

  • IOException — ファイルまたはネットワークの操作時のエラー。
  • SQLException — データベース操作時のエラー。
  • FileNotFoundException — ファイルが見つからない。

Error — JVM の致命的エラー用

Error は、Java 仮想マシン(JVM)レベルで発生するエラーの基底クラスです。通常、これはアプリケーションが処理できず、また処理すべきでもない深刻な障害です。Error が発生した場合、アプリケーションは継続実行できない可能性が高いです。

例:

  • OutOfMemoryError — メモリ不足。
  • StackOverflowError — スタックオーバーフロー(たとえば無限再帰による)。
  • NoClassDefFoundError — 必要なクラスが見つからない。

重要:
Error を捕捉・処理するのは、ほとんどの場合悪手です。これはあなたのプログラムの不具合ではなく、実行環境の障害です。

2. Checked vs Unchecked exceptions: それは何か?

Java の例外は大きく 2 つのグループに分かれます。

検査例外(Checked exceptions)

これは? コンパイラが処理するか、明示的にスローすることを強制する例外。

いつ発生する? 通常、外部リソースに関係します(ファイル、ネットワーク、データベース、ユーザー入力)。

どう扱う? コードを try-catch で囲むか、メソッドのシグネチャに throws を追加します。

例: IOException, SQLException, FileNotFoundException

例:

public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path); // IOException を投げる可能性がある
    // ...
}

処理またはスローを行わない場合、プログラムはコンパイルできません。

非検査例外(Unchecked exceptions)

これは? コンパイラが必須の処理を要求しない例外。

いつ発生する? 通常はプログラムのロジックの誤り(ゼロ除算、配列の範囲外アクセス、null 参照など)。

どう扱う? 捕捉してもかまいませんが必須ではありません。検証によって未然に防ぐのが望ましいです。

階層上の位置は? すべて RuntimeException を継承します。

例: NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException, ArithmeticException

例:

int[] arr = {1, 2, 3};
System.out.println(arr[10]); // ArrayIndexOutOfBoundsException

コンパイラはこの例外の捕捉を強制しませんが、発生するとプログラムはクラッシュします。

3. 階層を 1 枚の図で

graph TD
    Throwable --> Error
    Throwable --> Exception
    
    Exception --> RuntimeException
    Exception --> CheckedExceptions["(その他の Checked Exceptions)"]
    
    Error --> OutOfMemoryError
    Error --> StackOverflowError
    
    RuntimeException --> NullPointerException
    RuntimeException --> IndexOutOfBoundsException
    RuntimeException --> IllegalArgumentException

    %% スタイル
    style Throwable fill:#ffa64d,color:#000
    style Exception fill:#ffa64d,color:#000
    style CheckedExceptions fill:#ffa64d,color:#000
    
    style Error fill:#ff4d4d,color:#fff
    style OutOfMemoryError fill:#ff4d4d,color:#fff
    style StackOverflowError fill:#ff4d4d,color:#fff
    
    style RuntimeException fill:#4dff88,color:#000
    style NullPointerException fill:#4dff88,color:#000
    style IndexOutOfBoundsException fill:#4dff88,color:#000
    style IllegalArgumentException fill:#4dff88,color:#000

表: 主な相違点

グループ 親クラス 処理が必須か? 例
Checked Exception
Exception
はい
IOException, SQLException
Unchecked
RuntimeException
いいえ
NullPointerException, IndexOutOfBoundsException
Error
Error
いいえ
OutOfMemoryError, StackOverflowError

4. コードではどう見える?

Checked Exception: ファイルの例

import java.io.*;

public class FileDemo {
    public static void main(String[] args) {
        try {
            FileReader reader = new FileReader("nofile.txt"); // FileNotFoundException (checked)
            int data = reader.read();
            System.out.println(data);
            reader.close();
        } catch (IOException e) {
            System.out.println("ファイル処理中のエラー: " + e.getMessage());
        }
    }
}

コンパイラは IOException の処理を要求します!

Unchecked Exception: ゼロ除算の例

public class ExceptionDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        int c = a / b; // ArithmeticException (unchecked)
        System.out.println("結果: " + c);
    }
}

コンパイラは処理を要求しませんが、プログラムはクラッシュします。

5. なぜ例外の階層が必要か?

  • 柔軟な処理: 特定のエラー(FileNotFoundException)だけでなく、グループ全体(IOException や Exception)も捕捉できます。
  • コードの再利用: 同種のエラーを一元的に処理できます。
  • コードの明瞭性: 主要なロジックが細かな検証コードで散らからずに済みます。

例:

try {
    // 危険なコード
} catch (FileNotFoundException e) {
    System.out.println("ファイルが見つかりません!");
} catch (IOException e) {
    System.out.println("入出力エラー!");
} catch (Exception e) {
    System.out.println("問題が発生しました: " + e.getMessage());
}

6. 例外処理でよくある誤り

誤り № 1: 例外の無視。 catch (Exception e) {} と書くのはよくありません。エラー原因の情報を失います。

誤り № 2: 捕捉しすぎ。 catch (Exception e) は予期しないものまで何でも捕捉します。自分が適切に処理できる例外だけを捕捉しましょう。

誤り № 3: Error を捕捉する。 低レベルコードを書いていない限り、Error を捕捉すべきではありません。これは JVM の問題であり、あなたのプログラムの問題ではありません。

誤り № 4: checked と unchecked を区別しない。 すべての例外が同じではありません! checked は処理が必須(Exception)、unchecked は必須ではありません(RuntimeException とそのサブクラス)。

誤り № 5: 例外に情報を追加しない。 独自の例外を作成する場合は、必ず情報量のあるメッセージを付与しましょう。

1
タスク
JAVA 25 SELF, レベル 24, レッスン 0
ロック未解除
例外の謎を解く:親クラスの階層
例外の謎を解く:親クラスの階層
1
タスク
JAVA 25 SELF, レベル 24, レッスン 0
ロック未解除
どちらが上位?例外とエラーの違い
どちらが上位?例外とエラーの違い
1
タスク
JAVA 25 SELF, レベル 24, レッスン 0
ロック未解除
通知システム: チェックされる脅威とチェックされない脅威
通知システム: チェックされる脅威とチェックされない脅威
1
タスク
JAVA 25 SELF, レベル 24, レッスン 0
ロック未解除
ロボット司書とその「救出プラン」
ロボット司書とその「救出プラン」
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION