Java 例外処理マスター:try-catch、finally、クラス階層
Java の例外とは?
Java の例外 は、プログラム命令の実行を中断し、通常の制御フローを乱すイベントです。メソッド内で発生したエラー情報をカプセル化し、ランタイムシステムに渡すオブジェクトです。Java では、例外は主に標準制御フローでは処理できないさまざまなエラー状況を通知します。
このチュートリアルで学ぶこと:
- 例外とは何か
- なぜ例外が重要か
- 効果的な例外処理方法
- try-catch 構造
- Java の例外クラス階層
- finally ブロックの役割
Java のエラーは大きく2つに分類されます:
- コンパイル時エラー
- 実行時エラー
コンパイル時エラーはさらに:
- 構文エラー
- 意味エラー
構文エラー例:
int a; は正しいが、in a; と書くとコンパイラがエラーを報告。
同じスコープで int a; を一度宣言してから再度 int a; と宣言しようとすると、ビルド時にコンパイラエラーがハイライトされます。
実行時エラー例
実行時エラーは例外として現れ、正常な実行フローを中断します。典型例は ArithmeticException、NullPointerException、ゼロ除算など。
これらは開発者の直接的な制御を超えた条件から生じます。

なぜ例外処理が必要か?
リモートサーバーにアクセスするプログラムを考えます。開発時はサーバーが到達可能でコードはスムーズに動きます。本番ではサーバーがダウンしており、接続試行時に例外が発生します。

コードの自然なフローのみに頼るのは不十分。堅牢なプログラムは例外的状況を予期し、優雅に復旧します。
例外の処理方法
例外処理とは、例外的状況を予期し、フォールバックロジックを提供するプラクティスです。一般的な戦略は、主要操作を試み、失敗時にバックアップに切り替えることです。

従来の if-else 構造で複数の例外タイプを処理しようとするとすぐに手に負えなくなります:
class Connect {
if (serverIsUp()) {
// プライマリサーバーに接続
} else {
// バックアップサーバーに接続
}
}
try-catch ブロック
Java は例外処理の組み込みメカニズムを提供します。例外をスローする可能性のあるコードを try ブロックに、対応する復旧コードを1つ以上の catch ブロックに配置します。

例えば、try ブロックでプライマリサーバーへの接続を試み、catch ブロックでフォールバックロジックを処理します。
サーバーが稼働中なら catch ブロックはスキップされ、ダウン時は例外がスローされ catch ブロックが実行されます。

try-catch の構文:
try {
// 例外をスローする可能性のある文
} catch (ExceptionType name) {
// 復旧文
}
実践例
ステップ 1: 以下のコードを IDE にコピー。
class JavaException {
public static void main(String args[]) {
int d = 0;
int n = 20;
int fraction = n / d; // ArithmeticException をスロー
System.out.println("End Of Main");
}
}
ステップ 2: コンパイルして実行。プログラムは ArithmeticException をスローし、5行目で終了。
ステップ 3: try-catch を使用するように修正:
class JavaException {
public static void main(String args[]) {
int d = 0;
int n = 20;
try {
int fraction = n / d;
System.out.println("This line will not be executed");
} catch (ArithmeticException e) {
System.out.println("Caught exception: " + e);
}
System.out.println("End Of Main");
}
}
ステップ 4: 再コンパイル・実行。出力は例外が優雅に処理され、プログラムが最終出力文まで継続することを示します。

捕捉された ArithmeticException オブジェクト e には詳細情報が含まれ、ログ記録や復旧に利用できます。
例外クラス階層
Java の例外階層は Throwable クラスから派生し、2つの直接サブクラス Error と Exception を持ちます。Error は回復不能な状態(例:OutOfMemoryError)を表し、Exception はプログラムで処理可能な状態をカバーします。

- RuntimeException(例:NullPointerException、ArithmeticException) – コンパイル時に検出されない非チェック例外
- IOException – 入出力操作中に発生する問題
- InterruptedException – スレッドが中断されたときにスロー
ネスト try-catch 例
以下のコードをコピー:
class JavaException {
public static void main(String args[]) {
try {
int d = 1;
int n = 20;
int fraction = n / d;
int g[] = {1};
g[20] = 100; // ArrayIndexOutOfBoundsException
} catch (ArithmeticException e) {
System.out.println("Caught ArithmeticException: " + e);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Caught ArrayIndexOutOfBoundsException: " + e);
}
System.out.println("End Of Main");
}
}
d が 1 のとき ArrayIndexOutOfBoundsException がスローされます。d を 0 に変えると ArithmeticException が発生。広範な catch (Exception e) をアンコメントすると、より具体的なハンドラをシャドーイングするためコンパイルエラーになります。
finally ブロック
finally ブロックは例外の有無にかかわらず実行されるため、クリーンアップタスクに最適です。
try {
// リスキーな操作
} catch (ExceptionType e) {
// エラー処理
} finally {
// クリーンアップアクション
}
例:
class JavaException {
public static void main(String args[]) {
try {
int d = 0;
int n = 20;
int fraction = n / d;
} catch (ArithmeticException e) {
System.out.println("Caught exception: " + e);
} finally {
System.out.println("Inside the finally block");
}
}
}
このプログラムを実行すると、例外がスローされても finally ブロックのメッセージが出力されます。d を 1 に変えて例外が発生しなくても、finally ブロックは依然として実行されます。
まとめ:
- 例外 は正常なプログラムフローを中断する実行時エラー
- エラーはコンパイル時(構文、意味)と実行時(例外)に分類
- 堅牢なアプリケーションは想定されるすべての例外を処理して安定性を維持
- Java の try-catch 機構がエラーの捕捉と復旧の標準的方法
tryブロックに例外をスローするコード、catchで処理、finallyでクリーンアップを保証
Java
- C++例外処理をマスター:try、catch、throwの実践例
- Python例外処理マスター:try、except、else、finallyを徹底解説
- Python例外処理をマスター:try、except、finally、raiseの効果的な活用
- Java例外ハンドリング完全攻略:try-catch、finally、throw、throws
- Java例外ハンドリング実践:try-catch-finallyとリソース管理
- Java複数例外処理のマスター:単一catchブロックで複数例外を捕捉
- Java String.charAt()完全解説:構文、戻り値、例外、実例
- Java String.endsWith()マスター:文字列サフィックスチェック実例付き
- Java BufferedReader でファイル読み込み:実践ガイドと例
- Javaで挿入ソート:わかりやすい例とステップバイステップガイド
- Java 9のTry-with-resources改善:よりクリーンなコードへ