このページでは、次のトピックについて説明します。
Java SE 7 以降では、単一の catch
ブロックで複数の例外型を処理できます。この機能により、コードの重複を減らし、広すぎる例外をキャッチしようという試みを減らすことができます。
次の例では、各 catch
ブロックに重複したコードが含まれています。
catch (IOException ex) { logger.log(ex); throw ex; catch (SQLException ex) { logger.log(ex); throw ex; }
変数 ex
の型が異なっているため、Java SE 7 より前のリリースでは、共通のメソッドを作成して重複したコードをなくすことは困難です。
Java SE 7 以降で有効な次の例では、重複したコードをなくすことができます。
catch (IOException|SQLException ex) { logger.log(ex); throw ex; }
catch
節では、このブロックで処理できる例外の型を、それぞれ縦棒 (|
) で区切って指定しています。
注:catch
ブロックで複数の例外型を処理する場合、catch
パラメータは暗黙的に final
になります。この例で、catch
パラメータ ex
は final
なので、これに catch
ブロック内で値を割り当てることはできません。
複数の例外型を処理する 1 つの catch
ブロックをコンパイルしたバイトコードは、それぞれ 1 つの例外型だけを処理する catch
ブロックを多数コンパイルしたものより小さくなります (したがって、より優れています)。複数の例外型を処理する catch
ブロックの場合、コンパイラで生成されるバイトコードに重複は発生しません。つまり、バイトコード内に例外ハンドラの繰り返しはありません。
Java SE 7 のコンパイラでは、再スローされる例外について以前のリリースの Java SE よりも正確な分析が実行されます。これにより、メソッド宣言の throws
節に、より具体的な例外型を指定できます。
次に例を示します。
static class FirstException extends Exception { } static class SecondException extends Exception { } public void rethrowException(String exceptionName) throws Exception { try { if (exceptionName.equals("First")) { throw new FirstException(); } else { throw new SecondException(); } } catch (Exception e) { throw e; } }
この例の try
ブロックは、FirstException
または SecondException
をスローする可能性があります。rethrowException
メソッドの宣言の throws
節でこれらの例外型を指定したい場合について考えます。Java SE 7 より前のリリースでは、これは不可能です。catch
節の例外パラメータ e
の型は Exception
であり、catch ブロックは例外パラメータ e
を再スローするため、rethrowException
メソッドの宣言の throws
節で指定できるのは例外型 Exception
だけです。
ただし、Java SE 7 では、rethrowException
メソッドの宣言の throws
節で例外型 FirstException
および SecondException
を指定できます。Java SE 7 のコンパイラは、文 throw e
からスローされる例外は try
ブロックからのものであること、また、try
ブロックからスローされる例外は FirstException
および SecondException
だけであることを判断できます。catch
節の例外パラメータ e
の型が Exception
であっても、コンパイラはこれが FirstException
または SecondException
のインスタンスであることを判断できます。
public void rethrowException(String exceptionName) throws FirstException, SecondException { try { // ... } catch (Exception e) { throw e; } }
catch
ブロック内で catch
パラメータに別の値が割り当てられると、この分析は無効にされます。ただし、catch パラメータに別の値が割り当てられる場合は、メソッドの宣言の throws
節で例外型 Exception
を指定する必要があります。
詳しく説明すると、Java SE 7 以降では、catch
節で 1 つ以上の例外型を宣言し、この catch
ブロックによって処理される例外を再スローする場合は、再スローされる例外の型が次の条件を満たしているかどうかがコンパイラで確認されます。
try
ブロックがそれをスローできること。catch
ブロックが前にないこと。catch
節のいずれかの例外パラメータのサブ型またはスーパー型であること。Java SE 7 のコンパイラを使用する場合は、throws
で宣言されているいずれかの型のスーパー型である例外を再スローできるため、rethrowException
メソッドの宣言の throws
節で例外型 FirstException
および SecondException
を指定できます。
Java SE 7 より前のリリースでは、catch
節のいずれかの例外パラメータのスーパー型である例外をスローすることはできません。Java SE 7 より前のリリースのコンパイラでは、文 throw e
で「unreported exception Exception
; must be caught or declared to be thrown」というエラーが生成されます。コンパイラは、スローされる例外の型が、rethrowException
メソッドの宣言の throws
節で宣言されているいずれかの型に割り当て可能かどうかを確認します。しかし、catch パラメータ e
の型は Exception
であり、これは FirstException
および SecondException
のサブ型ではなくスーパー型です。