Java例外処理

公開日: 2026-07-30 20:22 更新日: 2026-07-30 20:22 2088文字 11 min read ... ページビュー

この記事では、例外アーキテクチャ(ErrorとExceptionの分類)、try-catch-finallyとtry-with-resourcesの使い方、throwsとthrowの違い、カスタム例外のシナリオと推奨事項など、Javaの例外処理メカニズムについて体系的に説明します。例外を実際に処理可能なシナリオに適用し、盲目的にキャッチして無視しないようにし、例外スタック情報を保持し、明確なエラーフィードバックを提供し、リソースを自動的に管理するためにtry-with-resourcesを使用してコードのセキュリティと保守性を向上させることを推奨します。

Java 例外処理

例外処理は、プログラムの実行中に発生する例外を記述、渡し、処理するために使用されます。フェアユース例外はエラーを特定し、回復可能なシナリオで是正措置を講じるのに役立ちます。

異常メカニズムは通常の業務判断に代わるものではなく、プログラムがいかなる状況下でも動作し続けることを保証するものでもない。

1.異常なシステム

image-001
image-001

JavaでスローできるオブジェクトはすべてThrowableから継承されている。ErrorExceptionの2つのカテゴリーに分類される。

Error

Errorは通常、JVMまたは実行環境の重大な問題を示します。たとえば、OutOfMemoryErrorです。このような問題は通常のビジネスコードでは回復できないため、通常はビジネスコードに捕捉されても実行されません。

Exception

Exceptionはプログラムが処理可能な例外状況を表しており,引き続き実行時例外とチェック対象例外に分類できる.

実行時の異常

RuntimeExceptionとそのサブクラスは実行時例外に属する.コンパイラーはキャプチャや宣言を強制しません。一般的な型は以下のとおりです。

  • NullPointerException
  • ArrayIndexOutOfBoundsException
  • ClassCastException
  • ArithmeticException
  • IllegalArgumentException

通常、不正なパラメータ、オブジェクト状態エラー、プログラムロジックの欠陥に関連するランタイム例外は、多数のcatch隠された問題に頼るよりも、チェックサム修正コードによって回避されるべきです。

チェックアウト異常

RuntimeExceptionとそのサブクラスを除くExceptionは、通常、IOExceptionのように検査される異常に分類される。

コンパイラは、プログラムが次のいずれかの方式を取ることを要求します。

  • try-catchを使用します。
  • throwsで宣言し、呼び出し元への伝播を続行します。

“チェック済み”はコンパイル時に発生しますが、例外オブジェクトはプログラムが関連する文を実行するまで発生しません。

try-catch-finallyの使用

基本的な文法

try {
    // 可能出现异常的代码
} catch (SpecificException e) {
    // 处理特定异常
} catch (Exception e) {
    // 处理其他异常
} finally {
    // 通常用于释放资源或执行收尾操作
}

実施ルールは以下の通り。

  1. tryで例外がスローされない場合、対応するcatchは実行されません。

  2. tryで例外がスローされると、JVMは上から下へ型が一致する最初のcatchを探します。

  3. より具体的なサブクラス例外は、より広範な親クラス例外の前に書かなければならず、後続の分岐は到達できません。

  4. finallyは通常実行されますが、JVMが強制終了したり、プロセスがクラッシュしたり、System.exit()が実行されたりする特別な場合を除きます。

例:例

import java.util.InputMismatchException;
import java.util.Scanner;

public class ExceptionDemo {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        try {
            int i = scanner.nextInt();
            int j = scanner.nextInt();

            int result = i / j;
            System.out.println("相除结果:" + result);

            int[] arr = new int[5];
            System.out.println(arr[i]);
            System.out.println("计算完毕");
        } catch (ArithmeticException e) {
            System.out.println("除数不能为零");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("数组索引越界");
        } catch (InputMismatchException e) {
            System.out.println("请输入整数");
        } catch (Exception e) {
            System.out.println("程序出现其他异常");
            e.printStackTrace();
        } finally {
            scanner.close();
            System.out.println("输入资源已关闭");
        }

        System.out.println("程序继续执行");
    }
}

実際のプロジェクトでは、あいまいなプロンプトを出力した後だけ例外を無視してはいけません。通常、例外スタックを記録したり、明示的なエラーメッセージを返したり、現在のビジネスレイヤが理解できる型に例外を変換したりする必要があります。

try-with-resourcesの使用

try-with-resourcesはJava 7から提供されており、リソースを自動的にシャットダウンするために使用されています。リソースオブジェクトはAutoCloseableインタフェースを実装する必要があります。

伝統的な執筆

import java.io.FileInputStream;
import java.io.IOException;

public class ResourceDemo {

    public static void main(String[] args) {
        FileInputStream input = null;

        try {
            input = new FileInputStream("d:/a.txt");
            System.out.println(input.read());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

シャットダウンする前にNULL 判定を行う必要があります。そうしないと、リソースの作成に失敗した場合、finallyNullPointerExceptionが再び表示される可能性があります。

推薦書を書く

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyFileDemo {

    public static void main(String[] args) {
        try (
                FileInputStream input = new FileInputStream("d:/a.txt");
                FileOutputStream output = new FileOutputStream("d:/b.txt")
        ) {
            input.transferTo(output);
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("程序继续执行");
    }
}

注意事項:

  • try丸括弧内のリソースはAutoCloseableを実装する必要があります。
  • 複数のリソースを宣言する場合、クローズ順序は宣言順序と逆になります。
  • リソース変数は、tryブロック内で再割り当てできません。
  • Java 9 以降では、外部で宣言され、“実質不変”条件を満たすリソース変数も使用できるようになった。
  • ビジネスコードとclose()の両方で例外がスローされた場合、リソースをシャットダウンする際に発生した例外は抑制された例外として保存され、getSuppressed()で取得できます。

throwsを使用した例外宣言

throwsはメソッド宣言またはコンストラクタ宣言の後に書かれ、現在のメソッドが例外をキャッチせず、呼び出し元に例外を伝播させ続けることを示します。

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class FileService {

    public FileInputStream openFile(String path) throws FileNotFoundException {
        return new FileInputStream(path);
    }
}

throws自体は例外を処理しません。呼び出し元は例外をキャッチするか、throwsを使用してアップ宣言を続ける必要があります。

複数の例外を宣言できます。

public void execute() throws FirstException, SecondException {
    // 方法体
}

親例外が宣言された場合、通常はサブクラス例外を繰り返し宣言する必要はありません。

throwで例外をスローする

throwは、メソッド本体内で特定の例外オブジェクトを投げるために使用されます。

public void copy(String sourcePath, String targetPath) {
    if (sourcePath == null || targetPath == null) {
        throw new IllegalArgumentException("源路径和目标路径不能为空");
    }

    // 执行复制操作
}

プログラムがthrowに実行されると、現在のコードパスは直ちに中断され、例外を処理できる呼び出し層に制御が委ねられる。

throwthrowsの違い

キーワード使用位置作用
throwメソッドの内部。特定の例外オブジェクトを投げる
throwsメソッドまたはコンストラクタ宣言後呼び出し元に伝播する可能性のある例外型の宣言

6.異常な定義

ビジネス例外は、JDKが提供する例外型がビジネスの意味を明確に表現できない場合に定義できます。

チェック対象例外のカスタマイズ

public class InvalidEmailAddressException extends Exception {

    public InvalidEmailAddressException(String message) {
        super(message);
    }
}
public class EmailManager {

    public void sendEmail(
            String recipient,
            String title,
            String content
    ) throws InvalidEmailAddressException {
        if (recipient == null || recipient.isBlank()) {
            throw new InvalidEmailAddressException("收件人地址不能为空");
        }

        System.out.println("发送邮件成功");
    }
}

Exceptionの継承後、呼び出し元は例外をキャッチまたは宣言する必要があります。

カスタムの実行时例外

例外がパラメータエラーを示し、ビジネスルールが満たされておらず、各レイヤーコードに明示的にキャプチャさせたくない場合は、RuntimeExceptionを継承できます。

public class InvalidEmailAddressException extends RuntimeException {

    public InvalidEmailAddressException(String message) {
        super(message);
    }
}

チェック対象例外とランタイム例外の選択は、呼び出し元が回復できるかどうか、プロジェクトの例外処理仕様、およびフレームワーク規約を考慮して決定します。

7.例外処理の提案

  • 実際に処理できる例外をキャプチャし、無意味にキャプチャして無視しないでください。
  • 特定の例外のキャッチを優先し、広範すぎるExceptionを直接使用しないでください。
  • 元の例外をcauseとして保持し、問題の原因を失わないでください。
  • 通常のフロー制御に例外を使用しないでください。
  • 資源はtry-with-resourcesを優先して管理します。
  • 安定したエラーメッセージを外部に返し、完全な例外スタックと必要なコンテキストを内部に記録します。

気に入ったならばコメントを残してくださいね~

... ページビュー
© 2026 跨越星轨的客 @Hoshiumi
Powered by theme astro-koharu · Inspired by Shoka