カスタム例外: 独自のエラー型

具体的なエラーを表現。原因を明確に。

チェック例外
Exception。catchかthrows必須。
非チェック
RuntimeException。任意。
例外連鎖
原因を保持して投げ直す。
Labeled Envelope

カスタム例外は「ラベル付き封筒」。 **汎用例外** = 無地の封筒(中身不明) **カスタム例外** = 「User未登録」と書いた封筒

カスタム例外

Checked, Unchecked
// カスタム例外の定義
// チェック例外(Exception を継承)
public class UserNotFoundException extends Exception {
public UserNotFoundException(String message) {
super(message);
}
public UserNotFoundException(String message, Throwable cause) {
super(message, cause);
}
}
// 非チェック例外(RuntimeException を継承)
public class InvalidInputException extends RuntimeException {
public InvalidInputException(String message) {
super(message);
}
}
// 使用
public User findUser(String id) throws UserNotFoundException {
User user = repository.find(id);
if (user == null) {
throw new UserNotFoundException("User not found: " + id);
}
return user;
}
例外メッセージ
UserNotFoundException: User not found: 12345
Bad
// ❌ Bad: 汎用例外を投げる
throw new Exception("Something wrong");
// 何が起きたかわからない
Good
// ✅ Good: 具体的なカスタム例外
throw new UserNotFoundException("User ID: " + id);
// 原因が明確

パターン

Extra info, Chaining
// 例外に追加情報を持たせる
public class InsufficientFundsException extends Exception {
private final double currentBalance;
private final double requestedAmount;
public InsufficientFundsException(double current, double requested) {
super("Insufficient funds: " + current + " < " + requested);
this.currentBalance = current;
this.requestedAmount = requested;
}
public double getCurrentBalance() {
return currentBalance;
}
public double getRequestedAmount() {
return requestedAmount;
}
}
// 例外の連鎖
try {
// 低レベル操作
} catch (SQLException e) {
throw new DataAccessException("Failed to fetch user", e);
}
// チェック vs 非チェック
// チェック例外: 回復可能(ファイル未発見、ネットワークエラー)
// 非チェック例外: プログラムバグ(null参照、配列境界)
Tip: ビジネスロジックの例外は具体的に。

合格ライン

カスタム例外を作れる
チェック/非チェックを使い分けられる

参考リンク

演習課題

課題1: カスタム例外
ビジネスロジック用のカスタム例外クラスを作成してください。
課題2: 例外チェーン
原因例外を保持するカスタム例外を作成してください。

次のステップ