実務では「return で抜けるべきか」「throw(例外)で止めるべきか」は非常に重要な設計判断ポイントです。
ここでは、安全設計ベストプラクティスとして、初心者でも理解できるように図+コード+判断基準表で整理します。
1. 全体イメージ図:処理の抜け方
+-------------------------------+
| 処理フロー |
|-------------------------------|
| ① 通常終了 → return |
| ② 条件分岐で早期return |
| ③ 予期しない異常 → throw |
|-------------------------------|
| return = 正常な抜け道 |
| throw = 異常な抜け道 |
+-------------------------------+
2. 使い分けの基本方針表
| 分類 | 状況 | ベストプラクティス | 理由 |
|---|---|---|---|
| ✅ 正常終了 | 計算・処理が終わった | return 値 | 正常なフローの終端。呼び出し元が続行できる。 |
| ⚠️ 条件不一致 | 想定済み・異常ではない | return(早期return) | 想定内なので例外を使わずシンプルに抜ける。 |
| ❌ 異常終了 | 想定外エラー・入力不正 | throw new XxxException() | 呼び出し元に異常を伝える。ログ出力・上位でハンドル。 |
| 🚫 致命的エラー | 回復不能(DB停止・設定欠落) | throw + ログ + fail-fast | 続行しても危険。即停止+明示的な例外が安全。 |
3. コード比較(例題:ユーザー登録処理)
❌ NG例:全部 return で逃げる(異常も含む)
public boolean register(User user) {
if (user == null) {
return false; // ← 何が起きたかわからない
}
if (user.getName().isEmpty()) {
return false; // ← ログもなし
}
// DB登録...
return true;
}
Java問題点:
- 呼び出し元からは「false」しかわからず、原因不明。
- デバッグ・監視が困難。
✅ OK例:想定外は例外で伝える、安全設計版
public boolean register(User user) {
if (user == null) {
throw new IllegalArgumentException("user is null");
}
if (user.getName().isEmpty()) {
throw new ValidationException("名前が未入力です");
}
try {
userRepository.save(user);
return true;
} catch (SQLException e) {
log.error("DB登録に失敗", e);
throw new SystemException("DBエラー", e);
}
}
Java💡ポイント:
- 入力エラー → 「業務例外」として
throw - システム障害 → 「システム例外」として
throw - 正常終了 →
return
4. 安全設計チェックリスト
| チェック項目 | 内容 | ✅ 推奨 |
|---|---|---|
| 例外はログに残しているか | 原因追跡可能か | ✔ |
| 想定内の分岐は return で早期終了 | ネストを浅く保つ | ✔ |
| 想定外は例外で止める | fail-fast原則 | ✔ |
| 呼び出し元で例外をキャッチし処理継続するか | 適切にリカバリしているか | ✔ |
Exception ではなく意味のある例外型 | IllegalArgumentException, ValidationException 等 | ✔ |
5. 実務応用例(Spring Bootでの安全設計)
@PostMapping("/register")
public ResponseEntity<?> register(@RequestBody User user) {
try {
userService.register(user);
return ResponseEntity.ok("登録完了");
} catch (ValidationException e) {
return ResponseEntity.badRequest().body(e.getMessage());
} catch (SystemException e) {
log.error("システムエラー", e);
return ResponseEntity.internalServerError().body("内部エラー");
}
}
Java→
**業務的エラー(想定内)**はHTTP 400、
**システム障害(想定外)**はHTTP 500。
これが「安全設計での return vs throw の分岐」です。
6. まとめ:設計判断早見表
┌───────────────────┐
│ 想定内の条件分岐 → return │
│ 想定外の異常発生 → throw │
│ return = 正常な出口 │
│ throw = 緊急脱出口(警報つき) │
└───────────────────┘

