はじめに
Java を学び始めた人が必ずぶつかるのが 例外処理(Exception Handling)。
- 「try-catch は知ってるけど、何のためにあるのか分からない」
- 「throws と throw の違いが曖昧」
- 「チェック例外って何」
こういう声は研修でも本当に多くあります。
この記事では、例外処理の本質 → 文法 → 実践的な書き方の順で、ざっくり理解できるように整理していきます。
この記事で理解してほしいこと
- 例外処理とは何か、なぜ必要なのか
- try-catch-finally の正しい使い方
- throw / throws の違い
- チェック例外・非チェック例外
- try-with-resources の重要性
- 現場で嫌われる NG コードと OK コード
1. 例外処理とは何か
● 例外とは「プログラムが正常に続行できない状態」
例:
- ファイルが存在しない
- ネットワークに接続できない
- 数値のパースに失敗した
- 配列の範囲外アクセス
Java はこうした異常を 例外(Exception) として通知します。
2. try-catch-finally の基本
● 最も基本的な構文
try {
// 例外が発生する可能性のある処理
} catch (Exception e) {
// 例外発生時の処理
} finally {
// 成否に関わらず必ず実行される処理
}
● finally が使われる場面
- ファイルを閉じる
- DB接続を閉じる
- ロックを解放する
ただし、後述の try-with-resources が登場してからは finally の出番は減りました。
3. throw と throws の違い
● throw:例外を「投げる」
throw new IllegalArgumentException("不正な値です");
● throws:例外を「投げる可能性がある」と宣言する
void readFile() throws IOException {
Files.readAllLines(Path.of("data.txt"));
}
- throw → 実際に投げる
- throws → 投げる可能性を宣言する
この違いを理解すると、メソッド設計が一気に楽になります。
4. チェック例外 / 非チェック例外
Java 特有の概念で、初学者が最も混乱するポイントです。
● チェック例外(Exception)
コンパイル時に「処理しろ」と強制される
例:IOException, SQLException
● 非チェック例外(RuntimeException)
コンパイル時に強制されない
例:NullPointerException, IllegalArgumentException
● なぜ分かれているのか
チェック例外 → 回復可能な問題(ファイルが無いなど)
非チェック例外 → プログラムのバグ(null参照など)
5. try-with-resources(超重要)
Java 7 以降の必須構文。
IO や DB を扱うなら絶対に覚えるべきものです。
try (BufferedReader br = Files.newBufferedReader(Path.of("data.txt"))) {
System.out.println(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
- メリット
- 自動で close() してくれる
- finally が不要
- リソース漏れを防げる
- 現場での評価が高い
6. NG コードと OK コード
❌ NG:とりあえず catch して握りつぶす
try {
// ...
} catch (Exception e) {
e.printStackTrace();
}
理由:
- ログが標準出力に流れるだけで、実質的に何も対処していない
- 障害調査が困難になる
- 「例外握りつぶし」と呼ばれ嫌われる
⭕ OK:意味のある処理をする
try {
// ...
} catch (IOException e) {
logger.error("ファイル読み込みに失敗しました", e);
throw new RuntimeException("処理を続行できません");
}
ポイント:
- ログに残す
- 上位に伝播させる
- 例外の意味を明確にする
7. カスタム例外(独自例外)
業務システムではよく使われます。
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}
メリット:
- 業務エラーを明確に分類できる
- 例外ハンドリングが読みやすくなる
8. まとめ:例外処理は「エラーを隠す技術」ではない
例外処理の目的は 「異常を正しく伝え、システムを安全に動かすこと」です。
- 初心者がやりがちなcatch で握りつぶす
- 何でも Exception で受ける
- finally を乱用する
こうした書き方を避け、 try-with-resources や適切な 例外伝播 を使うことで、評価されるコードになります。