39

別の例外にネストされている例外をキャッチしたい。私は現在このようにしています:

} catch (RemoteAccessException e) {
    if (e != null && e.getCause() != null && e.getCause().getCause() != null) {
        MyException etrp = (MyException) e.getCause().getCause();
        ...
    } else {
        throw new IllegalStateException("Error at calling service 'service'");
    }
}

これをより効率的かつエレガントにする方法はありますか?

4

9 に答える 9

31

このような状況では、 ExceptionUtils#getRootCause()メソッドが非常に便利です。

于 2011-09-16T05:49:11.890 に答える
29

ネストされた例外を選択的に「キャッチ」する、これほど洗練された方法はありません。この種のネストされた例外を大量にキャッチした場合、コードをリファクタリングして共通のユーティリティ メソッドにすることができると思います。しかし、それでもエレガントでも効率的でもありません。

エレガントな解決策は、例外の入れ子をなくすことです。そもそも例外を連鎖させないか、(選択的に) ラップを解除して、ネストされた例外をスタックのさらに上に再スローします。

例外は、次の 3 つの理由で入れ子になる傾向があります。

  1. 元の例外の詳細がアプリケーションのエラー回復に役立つ可能性は低いと判断しましたが、診断目的でそれらを保存したいと考えています。

  2. 特定のチェック済み例外を許可しない API メソッドを実装していますが、コードがその例外をスローすることは避けられません。一般的な回避策は、チェックされていない例外内にチェックされた例外を「密輸」することです。

  3. あなたは怠け者で、関連のないさまざまな例外のセットを 1 つの例外に変えて、メソッド シグネチャに多数のチェック済み例外が含まれないようにしています1

最初のケースで、ラップされた例外を区別する必要がある場合、最初の仮定は間違っていました。最善の解決策は、ネストを取り除くことができるようにメソッド シグネチャを変更することです。

2 番目のケースでは、制御が問題のある API メソッドを通過したらすぐに例外をラップ解除する必要があります。

3 番目のケースでは、例外処理戦略を再考する必要があります。すなわち、適切に行う2


1 - 実際、Java 7 で複数例外の catch 構文が導入されたため、これを行う半正当な理由の 1 つがなくなりました。

2 - API メソッドを に変更しないでくださいthrows Exception。それは事態を悪化させるだけです。Exceptionメソッドを呼び出すたびに、「処理」または伝播する必要があります。それは癌です...

于 2010-06-02T07:19:16.257 に答える
24

e.getCause().getCause()本当にMyException. それ以外の場合、このコードはClassCastException. 私はおそらくこれを次のように書くでしょう:

} catch(RemoteAccessException e) {
    if(e.getCause() != null && e.getCause().getCause() instanceof MyException) {
        MyException ex = (MyException)e.getCause().getCause();
        // Do further useful stuff
    } else {
        throw new IllegalStateException("...");
    }
}
于 2010-06-02T06:36:07.530 に答える
2

例外処理を効率的かつエレガントにする理由はわかりませんが、効果的であることに落ち着きます。それらは、理由から例外と呼ばれます。

このコードはメンテナンスの悪夢です。コール スタックを再設計して、関心のある例外をスローすることはできませんか? 重要な場合は、メソッド シグネチャでそれを表示し、他の 2 つの例外にラップして非表示にしないようにする必要があります。

最初の (e != null) は不要です。

そして、3番目を e.getCause().getCause() instanceof MyException) に変更することができます

于 2010-06-02T06:41:39.533 に答える
1

以下のようにできます。

catch (RemoteAccessException e) {
    int index = ExceptionUtils.indexOfThrowable(e, MyExcetption.class)
    if (index != -1) {
         //handleMyException
    } else {
    }
}
于 2016-05-06T16:32:11.783 に答える
0

疑わしいですがinstanceof、例外が正しいタイプであるかどうかを確認できます。

編集:ネストされた例外がラップされる理由があるはずなので、ネストされた例外をキャッチする目的は何であるかを自問する必要があります。

于 2010-06-02T06:33:23.293 に答える
0

例外がカスタム例外 (例: MyException) によって引き起こされているかどうかを調査している場合は、次のインスタンスが見つかるまで while ループを反復できます。MyException.

boolean isCausedByMyException(Throwable exception) {
    do {
        if (exception instanceof MyException) {
            return true;
        }

        exception = exception.getCause();
    } while (exception != null);

    return false;
}
于 2021-10-14T12:12:50.687 に答える
-1

ここExceptionUtils.throwableOfThrowable()のように使用することもできると思います

于 2020-12-12T04:19:43.643 に答える