今回やること
例外は、実行中に通常どおり処理を続けられない状況を伝える仕組みです。年齢の文字列を整数へ変換し、成功と失敗をtry-catch-finallyで扱います。
前提: Java入門 #18 - HashSetまでを終え、条件分岐とメソッド呼び出しを理解していること。
tryで変換
├── 成功 → 結果を表示
└── 例外 → catchで入力エラーを表示
最後にfinallyを実行
1. 例外が起きる処理
int age = Integer.parseInt("16");
"16"は整数へ変換できます。"sixteen"のように変換できない文字列では、NumberFormatExceptionが投げられます。
例外を何も処理しなければ、その場所から通常処理を続けられず、呼び出し元へ伝わります。
2. try-catchで捕捉する
try {
int age = Integer.parseInt(input);
System.out.println("年齢: " + age);
} catch (NumberFormatException e) {
System.out.println("年齢は整数で入力してください");
}
tryには失敗する可能性のある処理、catchにはその例外を扱う処理を書きます。今回捕捉する型を具体的なNumberFormatExceptionにすると、何を想定しているか分かります。
catchへ進んだ場合、try内の例外発生後の行は実行されません。catch終了後に続きの処理へ進みます。
3. finallyで必ず行う処理を書く
finally {
System.out.println("入力確認を終了します");
}
finallyは成功・失敗のどちらでも実行されます。後片付けに使えますが、現在はファイルや通信を安全に閉じるtry-with-resourcesが適する場合もあります。
finallyに通常の結果判定を集めず、「どちらでも必要な処理」に限定します。
完成コードを動かす
ExceptionDemo.javaとして保存します。
public class ExceptionDemo {
static void checkAge(String input) {
try {
int age = Integer.parseInt(input);
System.out.println("年齢: " + age);
} catch (NumberFormatException e) {
System.out.println("年齢は整数で入力してください");
System.out.println("例外の種類: " + e.getClass().getSimpleName());
} finally {
System.out.println("入力確認を終了します");
}
}
public static void main(String[] args) {
checkAge("16");
checkAge("sixteen");
}
}
javac ExceptionDemo.java
java ExceptionDemo
1回目は正常に変換し、2回目はcatchへ進みます。finallyは2回とも実行されます。
成功確認
次の内容が順に確認できれば成功です。
"16"では年齢: 16"sixteen"では入力エラーとNumberFormatException入力確認を終了しますは2回表示
例外が起きても、想定したcatchで処理され、Javaの長いスタックトレースだけを利用者へ見せずに終了できます。
例外情報の扱い
e.getClass().getSimpleName()は例外の種類、e.getMessage()は詳細メッセージを調べる材料です。ただしメッセージには入力値、ファイルパス、接続情報などが含まれる場合があります。
利用者向けには安全な文を表示し、ログでもパスワード、token、個人情報を含めません。調査に必要な情報と、保存してよい情報を分けます。
例外を空のcatchで無視すると、処理が成功したように見えます。少なくとも利用者への結果、再試行、記録、呼び出し元への伝播のどれを行うか決めます。
throw・throwsとの境界
この例ではInteger.parseIntが例外を投げ、checkAgeがその場でcatchしました。メソッドが自分で例外を作るthrowや、呼び出し元へ処理を任せるthrowsは、次の記事で扱います。
この回の目標は、既に投げられた例外を適切な型で捕捉し、成功時と失敗時の動きを分けることです。
よくあるつまずき
すべてをExceptionでcatchする
想定していない不具合まで同じ表示で隠す可能性があります。まず起こり得る具体的な例外型を確認します。
catchで何もしない
失敗を見失います。利用者への表示や記録など、必要な対応を決めます。
finallyでreturnする
tryやcatchの結果を上書きし、流れが分かりにくくなります。finallyは後片付けへ限定します。
練習
在庫数の文字列"5"と"many"を整数へ変換するcheckStockを作ってください。成功時は在庫数、失敗時は安全なエラー文、finallyでは確認終了を表示します。
次のステップ
Java入門 #20 - throwsと例外の伝播で、処理方法を呼び出し元へ任せる設計を学びます。