同じcatch句で複数のJava例外をキャッチできますか?


699

Javaでは、私はこのようなことをしたいです:

try {
    ...     
} catch (/* code to catch IllegalArgumentException, SecurityException, 
            IllegalAccessException, and NoSuchFieldException at the same time */) {
   someCode();
}

...の代わりに:

try {
    ...     
} catch (IllegalArgumentException e) {
    someCode();
} catch (SecurityException e) {
    someCode();
} catch (IllegalAccessException e) {
    someCode();
} catch (NoSuchFieldException e) {
    someCode();
}

これを行う方法はありますか?

回答:


1131

これはJava 7以降で可能です。マルチキャッチブロックの構文は次のとおりです。

try { 
  ...
} catch (IOException | SQLException ex) { 
  ...
}

ただし、すべての例外が同じクラス階層に属している場合は、その基本例外タイプを単純にキャッチできることを覚えておいてください。

また、ExceptionAから直接または間接的にExceptionBが継承されている場合、同じブロックでExceptionAとExceptionBの両方をキャッチすることはできません。コンパイラは文句を言うでしょう:

Alternatives in a multi-catch statement cannot be related by subclassing
  Alternative ExceptionB is a subclass of alternative ExceptionA

81
TT- bitwise or|)演算子を再定義する理由 コンマ、またはより類似した意味を持つ演算子logical or||)を使用しないのはなぜですか?
ArtOfWarfare 2013年

11
@ArtOfWarfareおそらく、ジェネリックの複数の境界の構文を考え出した後は、もう問題にならないと彼らは考えていました。
JimmyB 2016年

12
XOR記号(I)はOR(||)、A |と同じではありません BはAまたはBのいずれかを意味します、両方は意味しません|| Bは、AまたはB、あるいはその両方を意味します。これにより、例外の場合は、exceptionAまたはexceptionBのいずれかになりますが、同時に両方になることはありません。彼らはXOR歌う使用の代わりに、または、例外はあなたが2つの例外を置けばそのうちの一つが、他のサブタイプでスローされたとき、あなたははっきりとそれを見ることができる理由です
user1512999

41
Javaでは@ user1512999、ビットごとのXORは^(キャレット)、ビットごとのORは| (パイプ) docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
Lewis Baumstark 2017年

6
マルチキャッチブロックでキャッチされた例外のタイプは、最も派生した共通の親
yanpas

104

正確にはJava 7の前ではありませんが、私はこのようなことをします:

Java 6以前

try {
  //.....
} catch (Exception exc) {
  if (exc instanceof IllegalArgumentException || exc instanceof SecurityException || 
     exc instanceof IllegalAccessException || exc instanceof NoSuchFieldException ) {

     someCode();

  } else if (exc instanceof RuntimeException) {
     throw (RuntimeException) exc;     

  } else {
    throw new RuntimeException(exc);
  }

}



Java 7

try {
  //.....
} catch ( IllegalArgumentException | SecurityException |
         IllegalAccessException |NoSuchFieldException exc) {
  someCode();
}

11
Java 6の例では、コンパイラーがどこから何がスローされるかを通知する機能が壊れていることに注意してください。
MichaelBlume 2013

2
@MichaelBlume True、これは悪いことではありません。元の例外は常にで取得できexc.getCause()ます。補足として、Robert C. Martin(とりわけ)は、チェックされていない例外を使用することを推奨しています(コンパイラーは、そこからどのような例外がスローされるかを認識していません)。彼の著書Clean codeの第7章:エラー処理を参照してください 。
user454322

4
Java 6の例では、新しい例外インスタンスを作成するthrow exc代わりに、つまりthrow new RuntimeException(exc)
David DeMar

5
読みやすさの観点から、これはかなり悪い習慣です。
Rajesh J Advani 14

3
Instanceof操作は少しコストがかかります。できるだけ回避することをお勧めします。
Paramesh Korrakuti、2015

23

Java 7では、次のような複数のcatch句を定義できます。

catch (IllegalArgumentException | SecurityException e)
{
    ...
}

16

例外の階層がある場合は、基本クラスを使用して、例外のすべてのサブクラスをキャッチできます。縮退の場合、すべての Java例外を次のようにキャッチできます。

try {
   ...
} catch (Exception e) {
   someCode();
}

一般的なケースでは、RepositoryExceptionが基本クラスで、PathNotFoundExceptionが派生クラスである場合は、次のようになります。

try {
   ...
} catch (RepositoryException re) {
   someCode();
} catch (Exception e) {
   someCode();
}

上記のコードは、1種類の例外処理でRepositoryExceptionとPathNotFoundExceptionをキャッチし、他のすべての例外はまとめて処理されます。Java 7以降、上記の@OscarRyzの回答に従って:

try { 
  ...
} catch( IOException | SQLException ex ) { 
  ...
}

7
BTWのcatch句は順番に処理されるため、親の例外クラスを子のクラスの前に置くと、呼び出されません。例:try {...} catch(Exception e){someCode(); } catch(RepositoryException re){//一度も到達していない}
Michael Shopsin 2010

4
実際には到達できないため、そのようなコードはコンパイルすらできません。
polygenelubricants 2010

15

いいえ、お客様ごとに1つ。

すべてのケースで同じアクションを実行する限り、java.lang.Exceptionなどのスーパークラスをキャッチできます。

try {
    // some code
} catch(Exception e) { //All exceptions are caught here as all are inheriting java.lang.Exception
    e.printStackTrace();
}

しかし、それはベストプラクティスではない可能性があります。例外をキャッチするのは、実際に処理する戦略がある場合のみにしてください。ロギングと再スローは「処理」ではありません。是正措置がない場合は、それをメソッドシグネチャに追加し、状況を処理できる誰かにバブリングさせてください。


20
java.lang.Exceptionのキャッチに関する部分を言い換えるように請願できますか?私はそれが例であることを理解していますが、この答えを読んで「ああ、そうだ、私は例外をキャッチするだけだ」と言う人もいるかもしれません。
Rob Hruska、2010

2
私はそれについては知っていましたが、やりたくありません...ああ、それでは、次のバージョンのJavaまで、4つのキャッチに行き詰まっていると思います...
froadie

@duffymo:ロギングと再スローの何が問題になっていますか?それがコードを散らかすことを除いて、それを捕まえないことと同等です、そうではありません。一般的なエラー処理戦略の観点から見た。悪いのは、ログを記録していて、再スローしないことです。
フランクOsterfeld

5
私は何かをログに記録して再スローすることを考えていません。何か意味のあることができる人にバブルアップさせたいと思います。例外が回避されるべきではない最後のレイヤー(たとえば、Webアプリのコントローラー)は、その場合にエラーをログに記録するレイヤーでなければなりません。
duffymo 2010

ログが自動的に生成されないのが不合理だと思うのは私だけですか?コードの一部が例外をスローする可能性があるたびに、同じ愚かなロギングメッセージをすべて書き込む必要があるようです。
ArtOfWarfare 2013年

10

Java 6(つまり、Android)でのuser454322の回答に対するより簡潔な(ただし、冗長性が低く、おそらくあまり好ましくない)代替策は、すべてExceptionのをキャッチしてを再スローRuntimeExceptionすることです。他のタイプの例外をスタックのさらに上位でキャッチすることを計画している場合(これを再スローしない限り)、これは機能しませんが、すべてのチェックされた例外を効果的にキャッチします

例えば:

try {
    // CODE THAT THROWS EXCEPTION
} catch (Exception e) {
    if (e instanceof RuntimeException) {
        // this exception was not expected, so re-throw it
        throw e;
    } else {
        // YOUR CODE FOR ALL CHECKED EXCEPTIONS
    } 
}

とは言っても、冗長性のために、ブール値またはその他の変数を設定し、それに基づいて、try-catchブロックの後にいくつかのコードを実行するのが最適な場合があります。


1
このアプローチは、コンパイラが「キャッチブロック」に到達できるかどうかを判断できないようにします。
the_new_mr 2016年

3

7より前の場合はどうですか:

  Boolean   caught = true;
  Exception e;
  try {
     ...
     caught = false;
  } catch (TransformerException te) {
     e = te;
  } catch (SocketException se) {
     e = se;
  } catch (IOException ie) {
     e = ie;
  }
  if (caught) {
     someCode(); // You can reference Exception e here.
  }

3
wuoldは良い解決策です。どのように最終的なコントロールを挿入する程度caughtfinallyブロック?
Andrea_86 2015年

これには、元の質問よりも多くの行が必要です。
Leandro Glossman、2015

1

はい。pipe(|)セパレータを使用する方法は次のとおりです。

try
{
    .......
}    
catch
{
    catch(IllegalArgumentException | SecurityException | IllegalAccessException | NoSuchFieldException e)
}

このコードスタイルは何ですか?キャッチブロックをトライブロックに?
Sam

1

kotlinの場合、現時点では不可能ですが、追加することを検討しています:ソース
しかし、今のところ、ちょっとしたトリックです:

try {
    // code
} catch(ex:Exception) {
    when(ex) {
        is SomeException,
        is AnotherException -> {
            // handle
        }
        else -> throw ex
    }
}

0

例外階層で親クラスになっている例外をキャッチします。これはもちろん、悪い習慣です。あなたのケースでは、共通の親例外はたまたま例外クラスであり、例外のインスタンスである例外をキャッチすることは確かに悪い習慣です-NullPointerExceptionのような例外は通常プログラミングエラーであり、通常はnull値をチェックすることで解決する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.