導入:なぜエラーハンドリングが重要なのか
実務におけるJavaアプリケーションの品質は、いかに例外を適切に制御できるかで決まります。不適切な例外処理は、予期せぬシステム停止やリソースリーク(メモリやファイルハンドルの枯渇)を招きます。本稿では、throws句の正しい使い方から、モダンなJava開発で必須となるtry-with-resources、Multi-catchまで、現場で即戦力となる知識を解説します。
基礎知識:Javaの例外階層とthrows句
Javaの例外は「Throwable」クラスを頂点とし、大きく「Error(重大な障害)」と「Exception(プログラムで対処可能な異常)」に分かれます。さらにExceptionは「RuntimeException(非チェック例外)」と「それ以外(チェック例外)」に分類されます。
throws句は、メソッド内で発生しうる「チェック例外」を、そのメソッドの呼び出し元へ処理を委譲する宣言です。これにより、メソッドが「どのような異常系を考慮すべきか」を呼び出し元に対して明示的に契約(API仕様)として提示できます。
実装/解決策:ベストプラクティス
現場では以下の原則を守ることが推奨されます。
1. 過度なthrowsを避ける:すべてのメソッドにthrowsを付けると呼び出し側が疲弊します。捕獲してリカバリ可能な例外は内部で処理しましょう。
2. try-with-resourcesの活用:Java 7以降、AutoCloseableを実装したリソース(Stream, DB接続等)は、この構文で確実にクローズします。
3. Multi-catchの利用:Java 7から導入された機能で、複数の例外を1つのcatchブロックで処理し、コードの重複を排除します。
サンプルプログラム:実用的なエラーハンドリング実装
以下は、ファイル読み込み処理を想定した、モダンな例外処理のコード例です。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.NoSuchFileException;
public class ExceptionSample {
// throwsで呼び出し元に例外処理の責任を明示する
public void readFile(String filePath) throws IOException {
// try-with-resources: 処理終了後に自動でclose()が呼ばれる
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
System.out.println(reader.readLine());
} catch (NoSuchFileException | NullPointerException e) {
// Multi-catch: 複数の例外をまとめて処理
System.err.println("ファイルが見つからない、またはパスが不正です: " + e.getMessage());
throw e; // 必要に応じて再スローする
} catch (IOException e) {
System.err.println("入出力エラーが発生しました: " + e.getMessage());
}
}
}
応用・注意点:現場で陥りやすい罠
1. 例外の握りつぶし(Empty Catch):catchブロック内で何もせず、ログも出さない実装は厳禁です。デバッグが不可能になります。必ずログを出力するか、適切な例外として再スロー(Exception Chaining)してください。
2. RuntimeExceptionの乱用:チェック例外をすべてRuntimeExceptionでラップしてスローする手法もありますが、APIの利用者側が「何をキャッチすべきか」が分からなくなるため、設計の意図を明確にする必要があります。
3. Errorはキャッチしない:OutOfMemoryErrorなどのErrorクラスは、プログラム側で回復不能な事態を示します。基本的には捕捉せず、JVMを再起動させるのが一般的な運用です。
これらを意識するだけで、コードの信頼性は劇的に向上します。ぜひ明日からの実装に取り入れてみてください。

コメント