例外処理
例外処理により、プログラムはより堅牢になります。このレッスンでは、Javaの例外処理メカニズムを学びます。
例外とは
例外はプログラムの実行中に発生するエラーです。
例外の分類
TEXT
Throwable
├── Error(重大なエラー、プログラムは処理できない)
│ ├── OutOfMemoryError
│ └── StackOverflowError
└── Exception(例外、プログラムは処理可能)
├── チェック例外(処理必須)
│ ├── IOException
│ └── SQLException
└── 非チェック例外(RuntimeException)
├── NullPointerException
├── ArrayIndexOutOfBoundsException
└── NumberFormatException
try-catch
構文
JAVA
try {
// 例外をスローする可能性のあるコード
} catch (例外型 変数名) {
// 例外を処理
}
例:基本的な例外処理
JAVA
public class TryCatchDemo {
public static void main(String[] args) {
try {
int result = 10 / 0;
System.out.println(result);
} catch (ArithmeticException e) {
System.out.println("算術エラー: " + e.getMessage());
}
System.out.println("プログラムは続行されます");
}
}
出力:
TEXT
算術エラー: / by zero
プログラムは続行されます
複数のcatchブロック
JAVA
try {
// 複数の例外をスローする可能性のあるコード
} catch (例外型1 e1) {
// 例外1を処理
} catch (例外型2 e2) {
// 例外2を処理
} catch (Exception e) {
// その他の例外を処理
}
例:複数のcatch
JAVA
public class MultiCatch {
public static void main(String[] args) {
try {
String s = "abc";
int num = Integer.parseInt(s);
int result = 10 / num;
} catch (NumberFormatException e) {
System.out.println("数値形式エラー: " + e.getMessage());
} catch (ArithmeticException e) {
System.out.println("算術エラー: " + e.getMessage());
} catch (Exception e) {
System.out.println("その他のエラー: " + e.getMessage());
}
}
}
try-catch-finally
finallyブロックは例外が発生しても発生しなくても、常に実行されます。
構文
JAVA
try {
// 例外をスローする可能性のあるコード
} catch (例外型 e) {
// 例外を処理
} finally {
// 常に実行
}
例:finally
JAVA
public class FinallyDemo {
public static void main(String[] args) {
try {
System.out.println("tryブロック");
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("catchブロック");
} finally {
System.out.println("finallyブロック");
}
}
}
出力:
TEXT
tryブロック
catchブロック
finallyブロック
例:リソース解放
JAVA
import java.io.*;
public class ResourceDemo {
public static void main(String[] args) {
FileReader reader = null;
try {
reader = new FileReader("test.txt");
// ファイルを読み取る
} catch (FileNotFoundException e) {
System.out.println("ファイルが見つかりません");
} finally {
// リソースを解放
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
try-with-resources
Java 7で導入され、リソースを自動的に閉じます。
構文
JAVA
try (リソース型 変数 = new リソース()) {
// リソースを使用
} catch (例外型 e) {
// 例外を処理
}
例:try-with-resources
JAVA
import java.io.*;
public class TryWithResources {
public static void main(String[] args) {
// リソースを自動的に閉じる
try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
String line = reader.readLine();
System.out.println(line);
} catch (IOException e) {
System.out.println("読み取りエラー: " + e.getMessage());
}
// readerは自動的に閉じられ、finallyは不要
}
}
throwとthrows
throw:例外をスロー
JAVA
public static int divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("ゼロで割ることはできません");
}
return a / b;
}
throws:例外を宣言
JAVA
public static void readFile(String path) throws FileNotFoundException {
FileReader reader = new FileReader(path);
}
例:throwとthrows
JAVA
public class ThrowDemo {
public static int divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("ゼロで割ることはできません");
}
return a / b;
}
public static void validateAge(int age) {
if (age < 0 || age > 150) {
throw new IllegalArgumentException("無効な年齢: " + age);
}
}
public static void main(String[] args) {
try {
System.out.println(divide(10, 0));
} catch (ArithmeticException e) {
System.out.println(e.getMessage()); // ゼロで割ることはできません
}
try {
validateAge(-5);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage()); // 無効な年齢: -5
}
}
}
カスタム例外
手順
- ExceptionまたはRuntimeExceptionを継承
- コンストラクタを提供
例:カスタム例外
JAVA
// カスタム例外クラス
public class InsufficientBalanceException extends Exception {
private double balance;
private double amount;
public InsufficientBalanceException(double balance, double amount) {
super("残高不足: " + balance + ", 引出: " + amount);
this.balance = balance;
this.amount = amount;
}
public double getBalance() {
return balance;
}
public double getAmount() {
return amount;
}
}
// カスタム例外の使用
public class BankAccount {
private double balance;
public BankAccount(double balance) {
this.balance = balance;
}
public void withdraw(double amount) throws InsufficientBalanceException {
if (amount > balance) {
throw new InsufficientBalanceException(balance, amount);
}
balance -= amount;
System.out.println("引出成功、残高: " + balance);
}
public static void main(String[] args) {
BankAccount account = new BankAccount(1000);
try {
account.withdraw(500); // 引出成功、残高: 500.0
account.withdraw(800); // 例外をスロー
} catch (InsufficientBalanceException e) {
System.out.println(e.getMessage());
System.out.println("残高: " + e.getBalance());
System.out.println("引出: " + e.getAmount());
}
}
}
一般的な例外
| 例外 | 説明 | 原因 |
|---|---|---|
NullPointerException |
ヌルポインタ | nullオブジェクトでメソッドを呼び出す |
ArrayIndexOutOfBoundsException |
配列インデックス範囲外 | 存在しないインデックスにアクセス |
NumberFormatException |
数値形式エラー | 文字列から数値への変換に失敗 |
ClassCastException |
クラスキャストエラー | ダウンキャストの型不一致 |
ArithmeticException |
算術エラー | ゼロで割る |
FileNotFoundException |
ファイルが見つからない | ファイルパスが間違っている |
IOException |
IOエラー | ファイルの読み書きに失敗 |
例外処理の原則
| 原則 | 説明 |
|---|---|
| 具体的な例外を最初に | 一般的な例外の前に具体的な例外をキャッチ |
| 例外を無視しない | 少なくともログに記録 |
| finallyでリソース解放 | またはtry-with-resourcesを使用 |
| 例外をフロー制御に使用しない | 例外はエラー用、フロー制御用ではない |
❓ よくある質問
Q ErrorとExceptionの違いは何ですか?
A Errorはプログラムが処理できない重大な問題です。Exceptionはプログラムがキャッチして処理できる問題です。
Q チェック例外と非チェック例外の違いは何ですか?
A チェック例外は処理必須(try-catchまたはthrows)。非チェック例外は処理不要です。
Q 什么时候カスタム例外を作成すべきですか?
A 残高不足やユーザーが見つからないなど、ビジネス例外のタイプを区別する必要がある場合。
📖 まとめ
- 例外はプログラムの実行中に発生するエラー
- try-catchで例外をキャッチし、finallyでリソースを解放
- throwで例外をスロー、throwsで例外を宣言
- try-with-resourcesでリソースを自動的に閉じる
- カスタム例外はExceptionまたはRuntimeExceptionを継承
📝 演習
- 例外処理: ファイルを読み取るメソッドを作成し、ファイルが見つからない場合と読み取りエラーを処理
- カスタム例外: 年齢バリデーションのためのAgeOutOfBoundsExceptionを定義
- リソース管理: try-with-resourcesを使用してファイルコピーを実装
次のレッスン
次のレッスンでは、実践:OOPを学びます — オブジェクト指向知識を適用します。



