Java 例外処理
例外処理は、プログラムの実行中に発生する例外を記述、渡し、処理するために使用されます。フェアユース例外はエラーを特定し、回復可能なシナリオで是正措置を講じるのに役立ちます。
異常メカニズムは通常の業務判断に代わるものではなく、プログラムがいかなる状況下でも動作し続けることを保証するものでもない。
1.異常なシステム

JavaでスローできるオブジェクトはすべてThrowableから継承されている。ErrorとExceptionの2つのカテゴリーに分類される。
Error
Errorは通常、JVMまたは実行環境の重大な問題を示します。たとえば、OutOfMemoryErrorです。このような問題は通常のビジネスコードでは回復できないため、通常はビジネスコードに捕捉されても実行されません。
Exception
Exceptionはプログラムが処理可能な例外状況を表しており,引き続き実行時例外とチェック対象例外に分類できる.
実行時の異常
RuntimeExceptionとそのサブクラスは実行時例外に属する.コンパイラーはキャプチャや宣言を強制しません。一般的な型は以下のとおりです。
NullPointerExceptionArrayIndexOutOfBoundsExceptionClassCastExceptionArithmeticExceptionIllegalArgumentException
通常、不正なパラメータ、オブジェクト状態エラー、プログラムロジックの欠陥に関連するランタイム例外は、多数のcatch隠された問題に頼るよりも、チェックサム修正コードによって回避されるべきです。
チェックアウト異常
RuntimeExceptionとそのサブクラスを除くExceptionは、通常、IOExceptionのように検査される異常に分類される。
コンパイラは、プログラムが次のいずれかの方式を取ることを要求します。
try-catchを使用します。throwsで宣言し、呼び出し元への伝播を続行します。
“チェック済み”はコンパイル時に発生しますが、例外オブジェクトはプログラムが関連する文を実行するまで発生しません。
try-catch-finallyの使用
基本的な文法
try {
// 可能出现异常的代码
} catch (SpecificException e) {
// 处理特定异常
} catch (Exception e) {
// 处理其他异常
} finally {
// 通常用于释放资源或执行收尾操作
}実施ルールは以下の通り。
-
tryで例外がスローされない場合、対応するcatchは実行されません。 -
tryで例外がスローされると、JVMは上から下へ型が一致する最初のcatchを探します。 -
より具体的なサブクラス例外は、より広範な親クラス例外の前に書かなければならず、後続の分岐は到達できません。
-
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 判定を行う必要があります。そうしないと、リソースの作成に失敗した場合、finallyにNullPointerExceptionが再び表示される可能性があります。
推薦書を書く
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に実行されると、現在のコードパスは直ちに中断され、例外を処理できる呼び出し層に制御が委ねられる。
throwとthrowsの違い
| キーワード | 使用位置 | 作用 |
|---|---|---|
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を優先して管理します。 - 安定したエラーメッセージを外部に返し、完全な例外スタックと必要なコンテキストを内部に記録します。
気に入ったならばコメントを残してくださいね~