例外処理の仕組みについて学びましょう。
問題
以下のプログラムを実行した場合、コンパイル時や実行時にエラーが発生する可能性があるものを選んでください。
public class ExceptionTest {
public static void main(String[] args) {
try {
printMessage();
} catch (Exception e) {
System.out.println("Exception caught: " + e);
}
}
static void printMessage() {
System.out.println("Hello");
int[] numbers = {1, 2, 3};
System.out.println(numbers[3]);
}
}
選択肢
- A. コンパイルエラーが発生する
- B. 実行時に例外がスローされる
- C. エラーも発生せず、「Hello」が出力される
- D. 無限ループになる
答えと解説
回答を見る
答え
B. 実行時に例外がスローされる
解説
Javaの例外処理では、プログラムの実行中に異常が発生した場合、それを例外として処理する仕組みがあります。
例外には大きく分けて、コンパイル時にチェックされる「チェック例外」と、実行時に発生する可能性がありコンパイル時にはチェックされない「非チェック例外」があります。
- 基本説明: このコードで問題になるのは、
printMessage()
メソッド内で配列の範囲外を参照している部分です。配列numbers
には3つの要素しかありませんが、numbers[3]
というインデックスは存在しないため、実行時にはArrayIndexOutOfBoundsExceptionという例外がスローされます。
例外発生時に備えて、メソッドを呼び出す側でtry-catch
ブロックを使用しているので、例外が発生してもプログラム全体がクラッシュするのを防ぎ、「Exception caught: …」というメッセージが表示されます。
- 誤答理由: 選択肢Aの「コンパイルエラーが発生する」は間違いです。このコードでは文法的に問題がないため、チェック例外は存在せず、コンパイルは正常に完了します。また、選択肢Cの「エラーも発生せず、"Hello"が出力される」は、配列の範囲外アクセスが無視されないため、誤りです。選択肢Dの「無限ループになる」も全く関係がありません。
ここでの重要なポイントは、「チェック例外」と「非チェック例外」の違い、そしてtry-catch
ブロックを使って例外を適切にキャッチし、対処することです。
- つまずきポイント: 初心者がよくつまずく原因として、配列やリストの範囲外アクセスをしてしまうことがあります。Javaでは配列のサイズを超えたインデックスにアクセスすると実行時例外が発生します。このような非チェック例外は、あらかじめ注意深くプログラムを書くことで防ぐことができます。
Javaでは例外処理を適切に書くことが、信頼性の高いプログラムを作るために重要です。
- 発展知識: Javaの例外処理の応用として、例外をスローするメソッド定義時には
throws
キーワードを使って、特定の例外がスローされる可能性があることを宣言できます。これにより、例外が発生した時にその情報をメソッドの使用者に伝えることができます。
チェック例外(例えばIOException
)は、呼び出し側に例外処理が強制されますが、非チェック例外(例えばArrayIndexOutOfBoundsException
)は、そのままスローされる設計です。