このページでは、次のトピックについて説明します。
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
のサブ型ではなくスーパー型です。