Java throw vs throws:実践例でマスターする例外ハンドリング
Java throw vs throws:実践例でマスターする例外ハンドリング
このガイドでは、Javaのthrowとthrowsキーワードを効果的な例外ハンドリングにどう使うか、実例で説明します。
Javaにおいて、例外は2カテゴリに分類されます:
- 非検査例外 —— コンパイル時でなく実行時に検証。例:
ArithmeticException、NullPointerException、ArrayIndexOutOfBoundsException、すべてのErrorサブクラス。 - 検査例外 —— コンパイラが強制。例:
IOException、InterruptedException、その他多数。
詳細については、Java Exceptionsを参照。
非検査例外は通常プログラミングミスを示し、捕捉より修正すべきです。一方検査例外は、呼び出し元が認識・ハンドリング必須の状態を表します。
throwsキーワードの使用
throws句は、メソッドが1つ以上の例外をスローし得ることを宣言し、責任を呼び出し元に委譲します。構文:
accessModifier returnType methodName() throws ExceptionType1, ExceptionType2 { /* code */ }
複数例外型をカンマ区切りで列挙可能です。
例1:検査例外の宣言
import java.io.*; class Main { public static void findFile() throws IOException { // IOExceptionをトリガーし得るコード File newFile = new File("test.txt"); FileInputStream stream = new FileInputStream(newFile); } public static void main(String[] args) { try { findFile(); } catch (IOException e) { System.out.println(e); } } }
出力**
java.io.FileNotFoundException: test.txt (No such file or directory)
test.txtが欠落している場合、FileInputStreamはFileNotFoundException(IOExceptionのサブクラス)をスローします。findFile()がthrows IOExceptionを宣言しているため、main()はハンドリングまたは伝播必須です。
複数例外のスロー宣言
単一throws句で複数例外型を宣言可能:
import java.io.*; class Main { public static void findFile() throws NullPointerException, IOException, InvalidClassException { // 潜在的にNullPointerException… // 潜在的にIOException… // 潜在的にInvalidClassException… } public static void main(String[] args) { try { findFile(); } catch (IOException e1) { System.out.println(e1.getMessage()); } catch (InvalidClassException e2) { System.out.println(e2.getMessage()); } } }
NullPointerExceptionは非検査のため、呼び出し元で捕捉・宣言不要です。
throws vs try...catchの使い分け
例外をスローし得るすべてのメソッドにtry...catchを埋め込むとコードが乱雑になりロジックが不明瞭になります。throws宣言ならメソッドシグネチャをクリーンに保ち、上位コードがエラー処理方法を決定できます。
throwキーワードの使用
throwステートメントは例外インスタンスを明示的にスローし、制御を最寄りの一致するcatchブロックに移すか、未ハンドルならプログラム終了させます。
構文:
throw throwableObject;
ここでthrowableObjectはThrowableまたはそのサブクラスのインスタンスです。
例2:非検査例外のスロー
class Main { public static void divideByZero() { throw new ArithmeticException("Trying to divide by 0"); } public static void main(String[] args) { divideByZero(); } }
出力**
Exception in thread "main" java.lang.ArithmeticException: Trying to divide by 0 at Main.divideByZero(Main.java:3) at Main.main(Main.java:7) exit status 1
ArithmeticExceptionは非検査のため、捕捉は任意です。
例3:検査例外のスロー
import java.io.*; class Main { public static void findFile() throws IOException { throw new IOException("File not found"); } public static void main(String[] args) { try { findFile(); System.out.println("Rest of code in try block"); } catch (IOException e) { System.out.println(e.getMessage()); } } }
出力**
File not found
ここでは、findFile()が検査IOExceptionをスローするため、呼び出し元はハンドリングまたは宣言必須。main()メソッドが例外を捕捉し、プログラム終了を防いでいます。
Java
- Java変数とリテラル:包括的ガイド
- Java入出力をマスター:表示、読み取り、データフォーマット
- Javaの式、文、ブロックを理解する
- Javaクラスとオブジェクト:実践ガイド
- Java抽象クラスとメソッド:包括的ガイド
- Javaネストクラスとインナークラス完全ガイド:種類、例、ベストプラクティス
- Java複数例外処理のマスター:単一catchブロックで複数例外を捕捉
- Javaオートボクシングとアンボクシング完全ガイド:実例とベストプラクティス
- Java文字列置換マスター:replace()、replaceAll()、replaceFirst()徹底解説
- Java String toLowerCase() & toUpperCase():ロケール対応テキストケース変換
- Javaオブジェクトとクラス:コアOOP概念を完全理解