1. 例外の入門
まずは簡単な例えから始めましょう。あなたのプログラムを道路を走る自動車だとします。順調に走っていても、突然のトラブルが起きることがあります。タイヤのパンク、ガソリン切れ、エンジンのオーバーヒートなどです。こうした状況を「処理」しなければ(例: スペアタイヤに交換する、給油する)、車は止まって先に進めません。プログラムでも同じで、例外を処理しなければプログラムは異常終了してしまいます。
例外 (exception) は、プログラムの実行中に何らかの問題が発生した瞬間に生成されるオブジェクトです。例外は「ストップ!何かがおかしい!」と知らせます。
例外が発生する代表的な状況:
- ゼロによる除算 (10 / 0)
- 存在しない配列要素へのアクセスの試み (arr[999])
- ディスクに存在しないファイルを開く
- 文字列 "abc" を数値に変換する (Integer.parseInt("abc"))
重要: 例外はコンパイルエラー(たとえばコードのタイポ)ではなく、プログラムの実行中に発生する問題です。
なぜ例外は「良い仕組み」なのか?
- クリーンなコード: プログラムの主要ロジックが、細かなチェックだらけで汚れにくくなります。
- 柔軟性: エラーを一元的に処理できます(例: ファイル読み取りのエラーを一箇所でまとめて扱う)。
- 信頼性: プログラムが不可解なメッセージとともに「落ちる」のではなく、何が起きたのかを具体的に伝えられます。
2. 例外 (Exceptions) とエラー (Errors) の違い
Java では、実行時に発生し得る問題は大きく 2 種類に分かれます。
エラー (Errors)
エラー は、Java 仮想マシン (JVM) 自体の動作不全に起因する、致命的で回復不能な問題です。通常はコンピュータ資源や JVM 内部の不具合に関連します。
エラーの例:
- OutOfMemoryError — メモリ不足。
- StackOverflowError — スタックのオーバーフロー(例えば無限再帰によって)。
重要: こうしたエラーは、通常プログラム側で処理しようとすべきではありません。
例外 (Exceptions)
例外 は、プログラムが対処できる(そして対処すべき)問題です。プログラムのロジック上のミスや外部要因(例: ユーザーが想定外の入力をした)によって発生します。
例外の例:
- NullPointerException — null をオブジェクトとして使おうとした。
- ArrayIndexOutOfBoundsException — 配列の範囲外アクセス。
- IOException — ファイル操作時のエラー。
Java の例外には 2 種類あります:
- Checked exceptions(チェック例外) — コンパイラが処理を要求する(例: IOException)。
- Unchecked exceptions(非チェック例外) — コンパイラは処理を要求しない(例: NullPointerException)。
図解: クラス階層の位置関係
graph TD
Throwable --> Error
Throwable --> Exception
Exception --> RuntimeException
Exception --> Checked["(その他の Exceptions)"]
style Throwable fill:#ffa64d,color:#000
style Exception fill:#ffa64d,color:#000
style Checked fill:#ffa64d,color:#000
style Error fill:#ff4d4d,color:#fff
style RuntimeException fill:#4dff88,color:#000
補足説明:
- Throwable — Java におけるエラーと例外階層のルート。
- Error — JVM の致命的エラー。通常は処理しない。
- Exception — 処理可能で、処理すべき「通常の」例外。
- RuntimeException — 非チェック例外(プログラミング上のミス)。
3. コードではどう見えるか?
例 1: ゼロ除算
public class ExceptionDemo
{
public static void main(String[] args)
{
int a = 10;
int b = 0;
int c = a / b; // ここで ArithmeticException が発生します!
System.out.println("結果: " + c);
}
}
何が起こるでしょうか?
プログラムはエラーで終了し、次のメッセージが表示されます:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ExceptionDemo.main(ExceptionDemo.java:5)
例 2: 存在しない配列要素へのアクセス
int[] arr = {1, 2, 3};
System.out.println(arr[10]); // ArrayIndexOutOfBoundsException
例 3: ファイル操作
import java.io.FileReader;
import java.io.IOException;
public class FileDemo
{
public static void main(String[] args) throws IOException
{
FileReader reader = new FileReader("nofile.txt"); // FileNotFoundException (checked)
int data = reader.read();
System.out.println(data);
reader.close();
}
}
では、これらの例外的な状況をどのようにスマートに処理するかを、これから見ていきましょう。
GO TO FULL VERSION