🛑 例外 (Exception) とは

例外とは、プログラムの実行中に発生する、処理を中断させるような問題やエラーのことです。

Javaの例外は大きく2種類に分けられます。

① 非検査例外 (Unchecked Exception)

  • コンパイル時にはチェックされない例外。
  • プログラマのミス(バグ)や、実行環境の異常が原因で発生することが多いです。
  • : NullPointerException (参照先がない)、ArrayIndexOutOfBoundsException (配列の範囲外アクセス)、ArithmeticException (0による割り算)。
  • 処理しなくてもコンパイルは通りますが、実行時に発生するとプログラムは停止します。

② 検査例外 (Checked Exception)

  • コンパイル時にチェックされる例外。
  • 外部要因や予期せぬ事態(ファイルが見つからない、ネットワークが切断されたなど)が原因で発生します。
  • 発生の可能性がある場合、必ず try-catch で処理するか、メソッドに throws を付けて呼び出し元に例外を渡す必要があります。処理しないとコンパイルエラーになります。
  • : IOException (入出力エラー)、FileNotFoundException (ファイルが見つからない)。

🩹 2. try-catch の基本的な使い方

例外が発生する可能性のある処理を try ブロックで囲み、例外が発生した場合の対応処理を catch ブロックで記述します。

基本の書式

Java

try {
    // 1. 例外が発生する可能性がある処理
    int result = 10 / 0; // ここで ArithmeticException が発生!
    System.out.println("この行は実行されない");
} catch (ArithmeticException e) {
    // 2. 発生した例外(ここでは ArithmeticException)を受け取る
    // 3. 例外が発生した場合に実行される処理(リカバリー処理やエラー通知)
    System.err.println("エラーが発生しました: 0で割ることはできません。");
    // 例外の詳細を出力(デバッグ用)
    e.printStackTrace();
} finally {
    // 4. (省略可能) 例外の有無にかかわらず、最後に必ず実行される処理
    System.out.println("処理を終了します。");
}

実行の流れ

  1. まず try ブロック内の処理が上から順に実行されます。
  2. try ブロック内で例外が発生すると、残りの try ブロック内の処理は中断されます。
  3. 発生した例外の型と一致する catch ブロックが実行されます。
  4. catch ブロックの処理が完了すると、finally ブロックがあればその処理が実行されます。
  5. finally ブロックの処理が完了した後、try-catch の次の処理が再開されます。

📚 3. catch の複数指定と finally

① 複数の catch ブロック

一つの try ブロックに対して、複数の種類の例外を想定し、それぞれに対応する catch ブロックを記述できます。

  • 注意: catch ブロックは上から順番に評価されます。継承関係にある例外を捕まえる場合、より具体的な(子クラスの)例外を先に記述し、より一般的な(親クラスの)例外を後に記述する必要があります。

Java

try {
    // ファイル操作や配列アクセスなど、複数の例外の可能性がある処理
} catch (FileNotFoundException e) {
    // ファイルが見つからなかった場合の処理
} catch (IOException e) {
    // その他の入出力エラーの場合の処理 (FileNotFoundExceptionの親クラス)
} catch (Exception e) {
    // 上記のどれにも当てはまらない、その他のすべての例外を捕捉
}

finally ブロック

finally ブロックは、例外が発生したかどうかに関わらず必ず実行されます。

  • 主に、ファイルやネットワーク接続など、開いたリソースを必ず閉じる(解放する)処理に使われます。

➡️ 4. throws による例外の委譲(投げつけ)

検査例外の場合、try-catch で処理する代わりに、throwsキーワードを使って呼び出し元に例外処理を任せる(例外を投げつける)こともできます。

Java

// IOExceptionが発生する可能性があることを宣言
public static void readFile() throws IOException {
    // ファイル操作などの処理
    // ... IOExceptionが発生する可能性のあるコード ...
}

public static void main(String[] args) {
    // readFileメソッドは検査例外を投げるので、呼び出し元で try-catch が必要
    try {
        readFile();
    } catch (IOException e) {
        System.err.println("ファイル処理中にエラーが発生しました。");
    }
}

これは、そのメソッド内で例外処理を完結させず、より適切な場所(例:ユーザーにエラーを通知する場所)で処理させるために使われます。