Javaにおける到達不能なcatchブロックとは?原因とコンパイルエラーの仕組みを解説
到達不能ブロック(Unreachable Block)とは
どのような状況でも制御が決して到達しない文のまとまりは、到達不能ブロック(unreachable block)と呼ばれます。Javaでは、このような到達不能なコードはサポートされておらず、コンパイルエラーとなります。
特に複数のcatchブロックを記述する場合には注意が必要です。Exceptionクラスを参照するcatchブロックは必ず最後に配置しなければなりません。これは、Exceptionがすべての例外クラスのスーパークラス(親クラス)であるためです。
つまり、複数のcatchブロックを並べる際には、具体的な例外クラスから順に、より一般的な例外クラスへと並べるのがルールです。具体的には、Exceptionのサブクラスを先に記述し、スーパークラスを後に記述します。もし逆にスーパークラスを先に、サブクラスを後に配置すると、後続のcatchブロックが実行されることがなくなり、コンパイラは「到達不能なcatchブロック(unreachable catch block)」エラーを出力します。
誤った記述例(構文)
try {
// 処理
} catch(Exception e) {
System.out.println(e);
} catch(NumberFormatException nfe) { // 到達不能ブロック。Javaではサポートされず、コンパイルエラーになる
System.out.println(nfe);
}上記の例では、Exception型のcatchブロックが先にあるため、NumberFormatException用のcatchブロックには決して制御が届きません。
catch句が「到達可能」と判断される条件
コンパイラは、以下の両方の条件が満たされる場合に、そのcatch句を到達可能とみなします。
- tryブロック内でスローされた検査例外(checked exception)が、そのcatch句のパラメータ型に代入可能であること。
- それより前に宣言されたcatch句の中に、パラメータ型が同じか、またはそのスーパークラスであるものが存在しないこと。
catch句が「到達不能」と判断される条件
逆に、以下の両方の条件が当てはまる場合、そのcatch句は到達不能とみなされます。
- catch句のパラメータ型Eが、非検査例外(unchecked exception)を一切含まないこと。
- tryブロック内でスローされる例外のうち、型がEの(狭義の)サブタイプであるものが、すでに前段のcatch句によってすべて処理されていること。
正しい記述例
次のコードでは、catchブロックが「具体的な例外 → 一般的な例外」の順に正しく並べられているため、コンパイルエラーは発生しません。
public class UnreachableBlock{
public static void main(String[] args) {
try {
int i = Integer.parseInt("abc"); // この文はNumberFormatExceptionをスローする
} catch(NumberFormatException nfe) {
System.out.println("このブロックはNumberFormatExceptionを処理します");
} catch(Exception e) {
System.out.println("このブロックはすべての例外型を処理します");
} catch (Throwable t) {
System.out.println("ThrowableはExceptionのスーパークラスです");
}
}
}実行結果
このブロックはNumberFormatExceptionを処理します
このように、Integer.parseInt("abc")はNumberFormatExceptionをスローするため、最初に一致したcatchブロックが実行されます。より具体的な例外から順にcatchブロックを配置することで、到達不能エラーを回避し、意図した例外処理を実現できます。
-
【Java】1つのtryブロックに複数のcatchブロックを定義する方法と優先順位の仕組み
はい、Javaでは1つのtryブロックに対して複数のcatchブロックを定義できます。これにより、発生しうる例外の種類ごとに異なる処理を記述でき、よりきめ細かいエラーハンドリングが可能になります。 複数のcatchブロックを使う際の基本ルール すべてのtryブロックには、必ず少なくとも1つのcatchブロック(またはfinallyブロック)を関連付ける必要があります。 tryブロック内で例外オブジェクトが検出されると、JVMはcatchブロックを記述された順序(上から下へ)で照合していきます。 最優先で判定されるのは常に最初のcatchブロックです。最初のcatchブロックでその例外を処理
-
Javaでcatchブロックなしのtryブロックは使える?finallyとの組み合わせを解説
はい、可能です。Javaでは、tryブロックにcatchブロックを付けずに、finallyブロックと組み合わせて使用することができます。finallyブロックは、tryブロック内で例外が発生したかどうかにかかわらず必ず実行されるという特徴があります。唯一の例外は System.exit() を呼び出した場合です。この場合、JVM自体が終了するため、finallyブロックは実行されません。この「try-finally」構文は、例外処理を行わなくても、後処理(リソースの解放や接続のクローズなど)を確実に実行したい場合に役立ちます。例1:基本的なtry-finally構文public class T