はじめに
Spring Boot で Web API を作っていると、
「このエラーはもっとわかりやすくしたい」
「業務エラーとシステムエラーを分けたい」
「ControllerAdvice で扱いやすい例外がほしい」
そんな場面が必ず出てきます。
そこで役立つのが
独自の例外クラス(カスタム例外)
です。
この記事では、例外クラスの作り方を
やさしく・実務で役立つ形 で整理していきます。
まずはコードを見て、そこから少しずつ理解していきましょう。
まずはコードを確認
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}@Service
public class UserService {
public User findById(Long id) {
return repository.findById(id)
.orElseThrow(() -> new UserNotFoundException("ユーザーが見つかりません"));
}
}このように、
独自の例外クラスを作って投げる
だけで、エラーの意味がぐっと明確になります。
コードのしくみを解説
例外クラスとは
一言でいうと、
「特定のエラーを表すための専用クラス」
です。
- 何が起きたのか
- どんな種類のエラーなのか
- どこで扱うべきなのか
を明確にできます。
RuntimeException を継承する理由
実務では、
RuntimeException を継承した“非チェック例外”
として作ることが多いです。
理由はシンプルで、
- throws を書かなくてよい
- 呼び出し側で強制的に catch しなくてよい
- ControllerAdvice でまとめて扱いやすい
というメリットがあるからです。
よく使う独自例外のパターン
リソースが見つからない系
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}入力値が不正なとき
public class InvalidRequestException extends RuntimeException {
public InvalidRequestException(String message) {
super(message);
}
}業務ルール違反
public class BusinessException extends RuntimeException {
public BusinessException(String message) {
super(message);
}
}外部 API のエラー
public class ExternalApiException extends RuntimeException {
public ExternalApiException(String message) {
super(message);
}
}用途ごとに例外を分けると、
ControllerAdvice での処理がとても書きやすくなります。
ControllerAdvice と組み合わせると最強
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<Map<String, String>> handleUserNotFound(UserNotFoundException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(Map.of("error", e.getMessage()));
}
}独自例外を作ることで、
「この例外が起きたらこのレスポンスを返す」
という設計がとても自然に書けます。
あわせて知っておきたいポイント
メッセージは利用者目線で
例外メッセージは API 利用者が読むこともあるため、
わかりやすい文章にするのが実務的です。
ログを残すかどうかは例外ごとに決める
- 業務エラー → WARN
- システムエラー → ERROR
など、レベルを分けると運用が楽になります。
エラーコードを持たせることもできる
public class BusinessException extends RuntimeException {
private final String code;
public BusinessException(String code, String message) {
super(message);
this.code = code;
}
}API の品質がさらに上がります。
使うときに気をつけたいこと
例外クラスを増やしすぎない
細かく分けすぎると管理が大変になります。
RuntimeException を継承するのが基本
チェック例外にすると、呼び出し側が煩雑になります。
例外は「業務エラー」と「システムエラー」を分ける
- 業務エラー → 想定内
- システムエラー → 想定外
この区別があると設計が安定します。
まとめ
例外クラスは、
「特定のエラーを表すための専用クラス」
です。
- RuntimeException を継承するのが基本
- 用途ごとに例外を分けると読みやすい
- ControllerAdvice と組み合わせると最強
- エラーコードやメッセージで API 品質が上がる
難しく聞こえますが、
「エラーをわかりやすくするためのクラス」
と理解できれば十分です。

独自例外を作れるようになると、
API の設計が一気に整い、保守性も高まります。
あなたの開発が、今日より少しだけ楽になりますように。

エラーにも名前をつけてあげると、なんだか仲良くなれそうだね。

コメント