Java例外ハンドリング実践:try-catch-finallyとリソース管理
Java例外ハンドリングをマスターする
Javaのtry-catch-finally機構とtry-with-resourcesがいかに堅牢でエラーフリーなコードの記述を助けるかを探求します。
try…catch構造はJavaでの優雅なエラーハンドリングの中心です。プログラムが実行時問題を予期し、クラッシュせずに応答できるようにします。
以下は標準的な構文です:
try { // 例外をスローし得るコード } catch (ExceptionType e) { // 例外をハンドル }
tryブロックには例外をスローし得るコードを含みます。例外発生時、制御は一致するcatchブロックにジャンプし、適切に反応できます。
例:ArithmeticExceptionのハンドリング
class Main { public static void main(String[] args) { try { int result = 5 / 0; System.out.println("This line is never reached."); } catch (ArithmeticException e) { System.out.println("Caught: " + e.getMessage()); } } }
出力**
Caught: / by zero
ここでは、ゼロ除算がArithmeticExceptionをトリガーします。catchブロックが捕捉し、プログラムクラッシュを防ぎます。
ヒント: finallyブロック実行のみに関心がある場合catchブロックを省略可能ですが、catchは先行するtryなしに存在できません。
finallyブロックの使用
finally節は例外スロー有無に関わらず実行を保証します:
class Main { public static void main(String[] args) { try { int result = 5 / 0; } finally { System.out.println("Cleanup actions run here."); } } }
出力**
Cleanup actions run here. Exception in thread "main" java.lang.ArithmeticException: / by zero at Main.main(Main.java:4)
finallyブロックはtryブロック後、例外が正常フローを中断しても実行されます。
Try、Catch、Finallyの組み合わせ
最も堅牢なコードは、エラー処理、報告、リソースクリーンアップのために3節すべてを使用します。ファイルハンドリング例を考えます:
import java.io.*; class ListOfNumbers { private int[] list = {5, 6, 8, 9, 2}; public void writeList() { PrintWriter out = null; try { System.out.println("Attempting to write to file."); out = new PrintWriter(new FileWriter("OutputFile.txt")); for (int i = 0; i < 7; i++) { out.println("Value at: " + i + " = " + list[i]); } } catch (Exception e) { System.out.println("Exception: " + e.getMessage()); } finally { if (out != null) { System.out.println("Closing PrintWriter"); out.close(); } else { System.out.println("PrintWriter not opened."); } } } } class Main { public static void main(String[] args) { new ListOfNumbers().writeList(); } }
出力**
Attempting to write to file. Exception: Index 5 out of bounds for length 5 Closing PrintWriter
配列境界違反が例外をトリガーし、捕捉・報告されます。finallyブロックがPrintWriterクローズを保証し、リソースリークを防ぎます。
ベストプラクティス: ファイル、ソケット、データベース接続のクローズなどクリーンアップロジックは常にfinallyブロックに配置。
注意: finallyはJVM終了時(System.exit())、finally内で例外発生時、スレッド突然終了時には実行されない場合があります。
複数例外タイプのハンドリング
単一tryに複数catch節を続けられ、各々特定例外に対応:
class ListOfNumbers { private int[] arr = new int[10]; public void writeList() { try { arr[10] = 11; } catch (NumberFormatException e) { System.out.println("NumberFormatException: " + e.getMessage()); } catch (IndexOutOfBoundsException e) { System.out.println("IndexOutOfBoundsException: " + e.getMessage()); } } } class Main { public static void main(String[] args) { new ListOfNumbers().writeList(); } }
出力**
IndexOutOfBoundsException: Index 10 out of bounds for length 10
ランタイムは最初のcatchを試み、一致しなければ次へ、一致するまで続きます。
1つのcatch節で複数例外を捕捉(Java 7+)
Java 7で、単一catchに例外型を結合する機能が導入され、重複を削減:
try { // リスキーなコード } catch (IOException | SQLException ex) { // 統合ハンドリング }
異なる例外を同一にハンドリングできる場合にこの機能を使用。
自動クリーンアップのためのTry-with-resources
try-with-resourcesステートメントは、AutoCloseableを実装するリソースを自動的にクローズします:
try (PrintWriter out = new PrintWriter(new FileWriter("OutputFile.txt"))) { // リソース使用 } catch (IOException e) { // I/Oエラー処理 }
リソースが括弧内で宣言されるため、例外発生時でもブロック終了時に自動的にクローズされます。
詳細については、公式Javaドキュメントのtry-with-resourcesを参照。
Java
- Java演算子をマスター:種類、構文、実践例
- Javaコメント:種類、使い方、ベストプラクティス
- Java拡張forループをマスター:構文、例、ベストプラクティス
- Java文字列をマスター:生成、メソッド、ベストプラクティス
- Javaインターフェース完全ガイド:概念、実装、ベストプラクティス
- Java無名インナークラス完全ガイド:定義、構文、実践例
- Java例外ハンドリング完全攻略:try-catch、finally、throw、throws
- Java複数例外処理のマスター:単一catchブロックで複数例外を捕捉
- Javaのtry-with-resourcesをマスターする:自動リソース管理の仕組みと活用法
- Javaアノテーション完全ガイド:種類、配置場所、実践例
- Javaアサーション完全ガイド:バグ早期発見とコード信頼性の向上