web-dev-qa-db-ja.com

例外をキャッチしてもRuntimeExceptionがキャッチされないのはなぜですか?

これは私には非常に奇妙です。 RuntimeExceptionは、Exceptionを継承するThrowableを継承します。

_catch(Exception exc) { /* won't catch RuntimeException */
_

しかし

_catch(Throwable exc) { /* will catch RuntimeException */
_

RuntimeExceptionは、チェックされていないという点で特別です。しかし、例外がキャッチされるかどうかではなく、例外を宣言する必要があるかどうかだけに適用される私の理解に。そして、それでも、なぜこのロジックがThrowableをキャッチすると壊れるのかわかりません。

ターミナル操作でRuntimeExceptionがスローされる可能性があるため、これは私にとって非常に重要です。このパターンの名前はわかりませんが、クラスEmailRollerCallbacksの配列を受け取ります。コードは次のようになります。

_for(Callback cb : callbacks) {
    try {
        cb.call(item);
    }
    catch(Exception exc) {
        logger.error("Error in callback: ", exc);
   }
}
_

したがって、これらのコールバックのいずれかがすべてのマシンメモリを消費する場合、OOMEのようなものが飛び回る必要がある場合です。しかし、NullPointerException?またはIndexOutOfBoundsException?これらはコールバックに影響しますが、他の実行を妨げることはありません。

また、これは少し企業設計です。さまざまなプログラマーまたはチームがコールバックを追加してアイテムを処理できますが、それらは互いに分離する必要があります。これは、これらのコールバックを互いに絶縁する責任があるプログラマーとして、エラーがすり抜けないようにするためにそれらに頼るべきではないことを意味します。 Exceptionをキャッチするのは正しい行である必要がありますが、それはRuntimeExceptionがすり抜けるためではありません。私のより一般的な質問は、ここで良いパターンは何ですか?ちょうどcatch(Exception | RuntimeException exc)ですが、継承のために構文エラーだと思いますか?

41
djechlin

Exceptiondoes catch RuntimeExceptionをキャッチするため、質問の前提に欠陥があります。デモコード:

public class Test {
    public static void main(String[] args) {
        try {
            throw new RuntimeException("Bang");
        } catch (Exception e) {
            System.out.println("I caught: " + e);
        }
    }
}

出力:

I caught: Java.lang.RuntimeException: Bang

次の場合、ループに問題が発生します。

  • callbacksはnullです
  • ループの実行中にcallbacksが変更される(配列ではなくコレクションの場合)

おそらくそれはあなたが見ているものですか?

116
Jon Skeet
catch (Exception ex) { ... }

[〜#〜] will [〜#〜] RuntimeExceptionをキャッチします。

Catchブロックに入れるものは何でも、そのサブクラスもキャッチされます。

23
Jan Zyka

Exceptionをキャッチすると、RuntimeExceptionをキャッチします

8
cmd

同様のシナリオに直面しました。それは、classAの初期化がclassBの初期化に依存していたために起こっていました。 classBの静的ブロックがランタイム例外に直面したとき、classBは初期化されませんでした。このため、classBは例外をスローせず、classAの初期化も失敗しました。

class A{//this class will never be initialized because class B won't intialize
  static{
    try{
      classB.someStaticMethod();
    }catch(Exception e){
      sysout("This comment will never be printed");
    }
 }
}

class B{//this class will never be initialized
 static{
    int i = 1/0;//throw run time exception 
 }

 public static void someStaticMethod(){}
}

そして、はい... Exceptionをキャッチすると、ランタイム例外もキャッチします。

3
rajya vardhan