🧠【初心者向け】例外処理の本質をやさしく解説(スタックトレース図解あり)
Java の例外(Exception)は、初心者がもっとも混乱しやすいテーマのひとつです。
- try-catch は何を「捕まえて」いるの?
- 例外はどこから来て、どこに飛んで行く?
- throw と throws の違いが分からない
- スタックトレースってどう読むの?
- Checked / Unchecked の違いは?
これらは “例外の内部構造と流れ” を理解すれば一気に整理できます。
この記事では、例外の仕組みを
図解 × 初心者向け解説 × ニッチな深掘り
で分かりやすく丁寧にまとめます。
結論
✔ try-catch がしているのは「例外オブジェクトの受け取り」
✔ 例外は “スタックを巻き戻しながら” 上位へ伝播する
✔ スタックトレースは「メソッド呼び出しの逆順ログ」
✔ Checked と Unchecked は「設計思想」の違い
✔ finally は “必ず実行する後片付け” を担当する
例外処理が難しく感じる理由3つ
① try-catch の「受け取るだけ」という本質が見えない
try が何をし、catch が何を受け取っているかが曖昧だと理解しづらい。
② 例外が「どこへ向かって飛ぶか」のイメージがない
例外は“発生箇所から上方向(呼び出し元)に伝播”します。
③ スタックトレースが読めない
例外の仕組みを知らないと、スタックトレースは「謎のログ」にしか見えない。
例外オブジェクトとは何か?
例外とはシステムが投げる “エラー情報を持つオブジェクト” です。
つまりただのクラスインスタンス。
new NullPointerException("message")
これが「例外の正体」。
try-catch の本質は「例外を受け取る仕組み」
try ブロックで例外が発生すると、
JVM が catch ブロックに 例外オブジェクトを渡す という動作になります。
🔹 図解(短線版)
try {
A(); ← ここで例外が出る
} catch (Exception e) {
e ← 例外オブジェクトが渡される
}
この “e” が例外の情報そのもの。
例外はどのように伝播するのか?(スタック巻き戻しの仕組み)
例外が発生すると、JVM は「呼び出しスタック」を逆方向へ辿り
キャッチされるまでメソッドを順に抜けていきます。
🔹 図解(短線版)
main()
├─ service()
│ ├─ repository()
│ │ └─ DBアクセス ← 例外!
例外が起きると👇
DBアクセス → repository → service → main
(どこかでcatchされるまで伝播)
これが スタック巻き戻し(Stack Unwinding)。
スタックトレースの読み方
例外メッセージの代表例👇
java.lang.NullPointerException
at com.example.Repository.find(Repository.java:25)
at com.example.Service.get(Service.java:14)
at com.example.Main.main(Main.java:8)
読み方は「上から下へ」。
- 1行目:例外の種類と概要
- 2行目:最初に失敗した行(原因)
- 3行目:その呼び出し元
- 4行目:さらに上の呼び出し元
🔥最重要ポイント
最上段(2行目)が原因箇所。
そこから順番に上へ読む。
Checked と Unchecked の違い(本質)
Java では例外には2種類あります👇
✔ Checked Exception
- コンパイル時に“対応を強制”される
- 例:IOException, SQLException
✔ Unchecked Exception
- RuntimeException のサブクラス
- 主に“プログラミングミス”系
- 例:NullPointerException, IllegalArgumentException
🔥 設計思想の違い
- Checked … 「回復できるエラー」
- Unchecked … 「回復不能 or ロジックエラー」
throw と throws の違い(図解で理解する)
throw = 例外を投げる(発生させる)
throws = 呼び出し元へ例外を伝える宣言
🔹 図解
throw new IOException();
↑ ここで例外が発生!
void read() throws IOException
↑ このメソッドはIOExceptionを投げる可能性があると宣言
finally は必ず実行される(ただし例外あり)
finally は例外の有無に関わらず実行されます。
よく使われる用途👇
- DB接続のクローズ
- ファイルハンドルの解放
- ロック解除
注意
System.exit() の場合は実行されない。
実務で役立つ例外処理のベストプラクティス
✔ 原因ではなく「責任のある層」で例外をキャッチ
例:DBエラーはService層でラップして返すなど。
✔ try ブロックは最小限に
広すぎると原因特定が困難。
✔ ログには例外の種類+メッセージ+トレース
特に stacktrace をログに出さないのは厳禁。
✔ 例外の再スロー(wrap)は有効
「情報を付与する」ことで可読性が向上。
ここまでのまとめ(初心者向け)
- try-catch は“例外オブジェクトを受け取る仕組み”
- 例外はスタックを逆方向に伝播(巻き戻し)
- スタックトレースは原因箇所 → 呼び出し元 の順で読む
- Checked は回復可能、Unchecked はロジックミス
- throw/throws の違いを理解するとスッキリする
▼▼ 深掘り編ここから ▼▼
深掘り編:例外発生時 JVM の内部で何が起きているか?
① JVM が例外オブジェクトを生成
new NullPointerException("message")
② メソッドのスタックフレームを巻き戻す
1つずつ破棄しながら
catch 節を探す。
③ 一致する catch が見つかれば制御を移す
なければ JVM は最終的に
スレッドを終了させる。
→ これが “Unhandled Exception” の正体。
この記事のまとめ
- 例外は「オブジェクト」として扱われる
- try-catch は「例外を受け取る」ただそれだけ
- 例外はスタックを巻き戻しながら伝播する
- スタックトレースの読み方は技術者の基本スキル
- Checked / Unchecked の本質は「設計思想」
- JVM内部の流れを知ると例外処理が直感的に理解できる
Deep Friendly Tech の一言(後書き)
例外処理を理解すると、
「なぜこの箇所で例外が起きたのか?」
「どこで適切にキャッチすべきか?」
が見えるようになります。
これは “Java を書けること” とは別次元の
実務力そのもの。
例外処理こそ、エンジニアの本質です。

コメント