別の例外にネストされている例外をキャッチします
-
23-10-2019 - |
質問
例外をキャッチしたいのですが、それは別の例外にネストされています。私は現在このようにやっています:
} 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'");
}
}
これをより効率的でエレガントにする方法はありますか?
解決
ネストされた例外を選択的に「キャッチ」するエレガントな方法はもうありません。この種のネストされた例外を多くキャッチした場合、コードを共通のユーティリティメソッドにリファクタリングできる可能性があると思います。しかし、それでもエレガントでも効率的でもありません。
エレガントなソリューションは、例外のネスティングを廃止することです。そもそも例外をチェーンしないでください。または、(選択的に)ネストされた例外をスタックの上にさらに巻き戻してretります。
例外は3つの理由でネストされる傾向があります。
元の例外の詳細がアプリケーションのエラー回復に役立つ可能性は低いと判断しましたが、診断目的でそれらを保存したいと考えています。
特定のチェックされた例外を許可しないAPIメソッドを実装していますが、コード 避けられない その例外を投げます。一般的な回避策は、未確認の例外内でチェックされた例外を「密輸」することです。
あなたは怠zyで、aを回しています 多様 メソッドの署名に多くのチェックされた例外がないことを避けるために、単一の例外に無関係な例外のセット1.
最初のケースでは、ラップされた例外を差別する必要がある場合、最初の仮定は正しくありませんでした。最良の解決策は、ネストを取り除くことができるように変更方法署名です。
2番目のケースでは、コントロールが問題のあるAPIメソッドに合格したらすぐに例外を解除する必要があります。
3番目のケースでは、例外処理戦略を再考する必要があります。つまり、適切に行います2.
1-確かに、これを行うための半平和の理由の1つは、Java 7に多標準キャッチ構文が導入されたためになくなりました。
2- APIメソッドを変更しないでください throws Exception
. 。それは事態を悪化させるだけです。今、あなたは今、「処理」または伝播する必要があります Exception
メソッドを呼び出すたびに。癌です...
他のヒント
ExceptionUtils#getRootCause() このような状況では、方法は非常に便利です。
チェックを追加して確認する必要があります 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("...");
}
}
私はこのような問題を解決しました。シンプルなユーティリティ方法を書くことで、引き起こされたチェーン全体をチェックします。
/**
* Recursive method to determine whether an Exception passed is, or has a cause, that is a
* subclass or implementation of the Throwable provided.
*
* @param caught The Throwable to check
* @param isOfOrCausedBy The Throwable Class to look for
* @return true if 'caught' is of type 'isOfOrCausedBy' or has a cause that this applies to.
*/
private boolean isCausedBy(Throwable caught, Class<? extends Throwable> isOfOrCausedBy) {
if (caught == null) return false;
else if (isOfOrCausedBy.isAssignableFrom(caught.getClass())) return true;
else return isCausedBy(caught.getCause(), isOfOrCausedBy);
}
使用すると、IFのリストを最も具体的な例外から最も具体的ではなく、フォールバックの他の節を作成するだけです。
try {
// Code to be executed
} catch (Exception e) {
if (isCausedBy(e, MyException.class)) {
// Handle MyException.class
} else if (isCausedBy(e, AnotherException.class)) {
// Handle AnotherException.class
} else {
throw new IllegalStateException("Error at calling service 'service'");
}
}
例外処理を効率的でエレガントにしたい理由はないと思います。私は効果的に落ち着きます。それらは理由で例外と呼ばれています。
このコードはメンテナンスの悪夢になります。興味のある例外をスローするためにコールスタックを再設計することはできませんか?それが重要である場合、メソッド署名はそれを表示し、他の2つの例外に包まれた非表示にしないでください。
最初(e!= null)は不要です。
また、3番目をe.getCause()に変更することができます。
以下のようにできます:
catch (RemoteAccessException e) {
int index = ExceptionUtils.indexOfThrowable(e, MyExcetption.class)
if (index != -1) {
//handleMyException
} else {
}
}
私は疑うでしょうが、あなたはチェックすることができます instanceof
例外が正しいタイプの場合。
編集:ネストされた例外が包まれている理由があるはずなので、ネストされたものをキャッチする目的は何かを自問する必要があります。