第7回では、クラスとオブジェクトという Java の核を学びました。 今回は、プログラムが 「想定外のエラーで突然落ちないように守る」 ための重要技術 ── 例外処理(try-catch) を学びます。
実務では、ユーザーが想定外の入力をしたり、ファイルが存在しなかったり、ネットワークが切れたりと、「思い通りに動かない場面」 が必ず出てきます。 このとき、例外処理を書いておかないと アプリが突然クラッシュ してしまいます。 本記事を読み終えると、堅牢なプログラムを書けるようになる第一歩を踏み出せます。
この記事のゴール
「なぜ例外処理が必要か」「try-catch の基本」「よくある例外の対処法」を理解し、自分で書ける状態になることです。
そもそも「例外」とは?
プログラムを動かしていると、「正常には進まない状況」 が突然発生することがあります。たとえば:
- 0 で割ろうとした(
10 / 0) - 配列に存在しない番号でアクセスした(
arr[100]) - 文字列を数値に変換しようとしたが、数値じゃなかった(
"abc"→ int) - ファイルを読もうとしたが、ファイルがなかった
このような状況を Java では 「例外(Exception)」 と呼びます。
例外が発生すると、プログラムは強制終了します。
しかし、現実のアプリではエラーが起きても 「やさしくメッセージを出して続行」 したいことがほとんど。そのために使うのが 例外処理(try-catch) です。
例外を体験してみる
まずは、わざと例外を起こしてみましょう。
public class ExceptionDemo {
public static void main(String[] args) {
int[] numbers = {10, 20, 30};
System.out.println(numbers[10]); // ❌ 配列に 10 番目はない!
System.out.println("ここは表示される?");
}
}
実行結果:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 3
at ExceptionDemo.main(ExceptionDemo.java:4)
エラーが発生し、「ここは表示される?」 の行はそもそも実行されません。これがプログラムが「落ちる」状態です。
💡
ArrayIndexOutOfBoundsExceptionは「配列の範囲を超えるアクセス」を意味する、最もよく出会う例外の 1 つ。第 5 回でも紹介しました。
try-catch の基本
例外が発生しそうな処理を try ブロック で囲み、もし発生したらどう対処するかを catch ブロック に書きます。
try {
// 例外が起きるかもしれない処理
} catch (例外の型 変数名) {
// 例外が起きたときの対処
}
実例: 配列の範囲外アクセス
public class TryCatchDemo {
public static void main(String[] args) {
int[] numbers = {10, 20, 30}; // 要素数 3 の配列(index は 0〜2 まで)
// try ブロック:例外が起こるかもしれない処理を囲む
try {
System.out.println(numbers[10]);
// ↑ numbers[10] は存在しないので ArrayIndexOutOfBoundsException が発生
// この瞬間に try ブロックの残りはスキップされ、catch に飛ぶ
}
// catch ブロック:例外が起きたときの対処を書く
// 引数 e に発生した例外オブジェクトが入る
catch (ArrayIndexOutOfBoundsException e) {
System.out.println("配列の範囲外にアクセスしました!");
// System.out.println(e.getMessage()); // ← 詳細メッセージも取れる
}
// try-catch の外:例外が起きてもプログラムは続行できる
System.out.println("プログラムは続行できる"); // ⭕ ちゃんと表示される
}
}
実行結果:
配列の範囲外にアクセスしました!
プログラムは続行できる
try-catch で囲んだ結果、プログラムは落ちずに続行できました。
1 行ずつ解説
} catch (ArrayIndexOutOfBoundsException e) {
ArrayIndexOutOfBoundsException: キャッチしたい例外の型(クラス名)e: 例外オブジェクトを受け取る変数名(慣習的にeをよく使う)- このブロック内で
e.getMessage()などで詳細を取得できる
finally 句:必ず実行したい処理
try または catch の後に finally ブロックを書くと、例外の有無に関わらず必ず実行される処理を書けます。
try {
// 何かの処理
} catch (Exception e) {
// エラー時の対処
} finally {
// 必ず実行される(例:ファイルを閉じる、接続を切る等)
System.out.println("お疲れさまでした!");
}
💡
finallyは「ファイルやネットワーク接続を確実に閉じたい」時に重宝します。リソース管理の基本パターンです。
よく出会う例外 TOP5(初心者向け)
① ArrayIndexOutOfBoundsException(配列範囲外)
int[] arr = {1, 2, 3};
arr[5]; // ❌
② NullPointerException(null 参照)
String s = null;
s.length(); // ❌ null のメソッドは呼べない
対処: 使う前に if (s != null) でチェック
③ NumberFormatException(数値変換失敗)
int n = Integer.parseInt("abc"); // ❌ "abc" は数値に変換できない
対処: 入力をチェック、または try-catch で囲む
④ ArithmeticException(0 除算)
int x = 10 / 0; // ❌
対処: 割る前に if (divisor != 0) でチェック
⑤ ClassCastException(型変換失敗)
Object obj = "hello";
Integer i = (Integer) obj; // ❌ String を Integer に変換不可
対処: 型を間違えない / instanceof でチェック
複数の catch を並べる
例外の種類によって対処を変えたいときは、catch を複数並べられます。
try {
String input = "abc";
int n = Integer.parseInt(input);
int[] arr = {1, 2, 3};
System.out.println(arr[n]);
} catch (NumberFormatException e) {
System.out.println("数値に変換できません");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("配列範囲外です");
} catch (Exception e) { // ↑ 以外をすべてキャッチ
System.out.println("予期しないエラー: " + e.getMessage());
}
⚠ 重要: 上から順にチェックされるので、具体的な例外を先に書くこと。
Exception(すべての親)を最初に書くと、後の catch が無効になります。
throw と throws(自分で例外を発生させる)
Java では、自分から例外を発生させることもできます。これを throw と呼びます。
public static int divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("0 で割ることはできません");
}
return a / b;
}
これで、divide(10, 0) を呼ぶと例外が発生し、呼び出し側で catch できます。
💡 入門段階では「自分から throw する」より、「標準ライブラリが投げる例外を catch する」ことのほうが多いです。
throwの出番は中級以降。
検査例外 vs 実行時例外(参考)
Java の例外には大きく 2 種類あります。
| 種類 | 例 | 特徴 |
|---|---|---|
| 検査例外(Checked) | IOException、SQLException | 必ず try-catch で囲むか throws で宣言が必要 |
| 実行時例外(Unchecked) | NullPointerException、ArithmeticException | 強制ではないが、対処すべき |
入門段階では「ファイル操作や DB の例外は検査例外」「普段のバグ系は実行時例外」と理解すれば OK。
ハマりがちなエラー TOP3
エラー① catch の順序を間違える
try {
// ...
} catch (Exception e) { // ❌ 一番上に書いてはダメ
// ...
} catch (NumberFormatException e) { // ❌ ここは絶対に到達しない
// ...
}
対処: 具体的な例外を上、親の Exception を最後に。
エラー② 例外を握りつぶす
try {
// ...
} catch (Exception e) {
// ❌ 何もしない(エラーが起きても気づけない!)
}
対処: 最低限、ログを出力する。System.out.println(e.getMessage()) でも OK。
エラー③ try ブロックを広げすぎる
try {
// 100 行のコード...全部 try で囲む
} catch (Exception e) {
// どこでエラーが起きたか分からない
}
対処: 例外が起きそうな部分だけを try で囲む。
編集部より
「エラーで落ちないプログラム」を書けるようになると、実務エンジニアとしての信頼性が一気に上がります。例外処理は地味ですが、本物のエンジニアの証です!
練習問題
以下のプログラムを書いてみましょう。
ユーザーが入力した文字列を 整数に変換して 2 倍を表示する。 ただし、数値以外が入ったらエラーメッセージを出して、プログラムは続行する。
解答例
import java.util.Scanner; // キーボード入力用のクラスを使うため import
public class DoubleNumberDemo {
public static void main(String[] args) {
// ── ユーザー入力を読み取る ──
Scanner sc = new Scanner(System.in); // System.in = キーボード
System.out.print("数値を入力してください: ");
String input = sc.nextLine(); // 1 行読み取り(String 型)
// ── 例外が起こりそうな処理を try で囲む ──
try {
int n = Integer.parseInt(input); // 文字列→数値に変換(変換失敗で例外)
System.out.println("2 倍は: " + (n * 2));
}
// 「数値変換失敗」だけを狙ってキャッチ
catch (NumberFormatException e) {
System.out.println("⚠ 数値以外が入力されました: " + input);
}
// 例外が起きても起きなくても、必ず最後に実行される
finally {
System.out.println("プログラム終了");
sc.close(); // Scanner は使い終わったら閉じる
}
}
}
実行例(abc を入力した場合):
数値を入力してください: abc
⚠ 数値以外が入力されました: abc
プログラム終了
まとめ:Java入門シリーズ 完結!
第 8 回では、以下を学びました。
- ✅ 例外は「想定外の状況」のこと
- ✅
try-catchで例外をキャッチし、プログラムを落とさず続行できる - ✅
finallyで必ず実行する処理を書ける - ✅ よくある例外: ArrayIndexOutOfBounds / NullPointer / NumberFormat / Arithmetic / ClassCast
- ✅ catch は 具体的な例外を先、親を後 に並べる
- ✅
throwで自分から例外を発生させることもできる
これにて 「Java 入門シリーズ全 8 回」 が完結となりました。お疲れさまでした!
第 1 回〜第 8 回まで全部読み終えた方は、Java の基礎を一通りマスターしたことになります。 ここまでの知識があれば、簡単なアプリやツールは自力で作れるレベルになっています。
次のステップとしては:
- 配列の発展形「ArrayList(リスト)」
- 継承・インターフェース(オブジェクト指向の発展)
- ファイル入出力(実用的なプログラム)
- マルチスレッド(並列処理)
- Java フレームワーク(Spring など、Web 開発)
など、興味のあるテーマに進んでみてください。 入門シリーズが、皆さまの エンジニアキャリアの第一歩になれば幸いです!