注釈付きのランタイム例外によって例外をラップ
-
20-08-2019 - |
質問
メソッドに注釈を付ける方法はありますので、実行時例外に変換されてスローされるすべての例外自動的に?
@MagicAnnotation
// no throws clause!
void foo()
{
throw new Exception("bar")'
}
解決
少なくとも今の私は、この(簡体字)のような回避策を使用し、それをする方法はありません。
@SuppressWarnings({"rawtypes", "unchecked"})
public class Unchecked {
public static interface UncheckedDefinitions{
InputStream openStream();
String readLine();
...
}
private static Class proxyClass = Proxy.getProxyClass(Unchecked.class.getClassLoader(), UncheckedDefinitions.class);
public static UncheckedDefinitions unchecked(final Object target){
try{
return (UncheckedDefinitions) proxyClass.getConstructor(InvocationHandler.class).newInstance(new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (target instanceof Class){
return MethodUtils.invokeExactStaticMethod((Class) target, method.getName(), args);
}
return MethodUtils.invokeExactMethod(target, method.getName(), args);
}
});
}
catch(Exception e){
throw new RuntimeException(e);
}
}
}
と使用方法は次のようになります:
import static ....Unchecked.*;
...
Writer w = ...;
unchecked(w).write(str, off, len);
トリックは、そのインタフェースが「終わったことがない」と毎回私はどこかに未チェックの方法を必要とされている、私はオフにそのオブジェクトをラップしますし、IDEインターフェースにメソッドシグネチャを生成してみましょう。
実装は、汎用である(反射および「遅い」が、通常は十分な速さ)
があり、いくつかのコードをポストプロセッサとバイトコード-織工があるが、これは私の現在のプロジェクトのために(もないAOPや他のJVMベースの言語)ことはできませんでしたので、これは「発明」された。
他のヒント
プロジェクトロンボクの @SneakyThrows
のは、あなたが探しているものと考えられます。 (それは多くのケースで問題になる可能性があるため)本当にあなたの例外をラップしていない、それだけでコンパイル時にエラーになりません。
@SneakyThrows
void foo() {
throw new Exception("bar")'
}
あなたはAspectJのでこれを行うことができます。あなたはと「軟化」例外(メソッドfooのこの場合の呼び出しで)ジョインポイントを宣言します。
編集この上のビットを詳しく説明します:
Bar
あなたは以下のクラスを持っていると言います
public class Bar {
public void foo() throws Exception {
}
}
...とあなたが持っているこのようなテストます:
import junit.framework.TestCase;
public class BarTest extends TestCase {
public void testTestFoo() {
new Bar().foo();
}
}
すると、明らかにテストをコンパイルするつもりはありません。これは、エラーになります。
Unhandled exception type Exception BarTest.java(line 6)
今AspectJので、これを克服するために、あなたは非常に単純な側面を記述します:
public aspect SoftenExceptionsInTestCode {
pointcut inTestCode() : execution(void *Test.test*());
declare soft : Exception : inTestCode();
}
の態様は、基本的に言うことをテストの中から任意のコード(例:「テスト」で終わるクラスの「テスト」と始まる方法戻る「ボイド」)のAspectJによって受け入れなければならない例外をスローすることコンパイラ。例外が発生した場合は、AspectJのコンパイラによってRuntimeException
としてラップとスローされます。
確かに、あなたはEclipse内から(AJDTがインストールされている)のAspectJプロジェクトの一環として、このテストを実行する場合、テストは成功します、側面なしでそれもコンパイルされません一方ます。
私はそれは、バイトコードの再設計、カスタマイズされたコンパイラまたは多分アスペクト指向プログラミング 1 で可能だと思います。 Javaのに反して、C#が唯一の未チェックの例外 2 を持っています。
私はあなたがチェック例外を抑制したい理由を聞いても?
1 のマールテンWinkels のに従って、これが可能である。
2 と、彼らはいくつかのチャンネル9の動画によると、確認されたものを導入することを考えている。
の編集の問題については:それはあなたがそれらをチェック例外抑制の候補であることをフラグにあなたの方法に注釈を付けることができるという意味でも可能です。次に、実際の抑制/ラッピングを適用するには、いくつかのコンパイル時や実行時のトリックを使用します。
しかし、私はその方法の顧客を混乱させる可能性があるこれらの方法で例外をラップ、あなたのケースの周りの環境が表示されていないとして - 彼らはのRuntimeExceptionに対処するために準備されない場合があります。例:メソッドはIOExceptionがスローし、FileNotFoundExceptionをエラーダイアログを表示するようにクライアントがそれをキャッチします。あなたがのRuntimeExceptionにあなたの例外をラップする場合は、エラーダイアログが表示されません取得し、おそらくそれはあまりにも、呼び出し元のスレッドを殺します。 (私見)。
チェック例外は、メソッドの実装のresponsabilityです。 非常に非常に慎重にこの事実を取ります。あなたはそのような回避策の成果物を使用しないことができるかどうか。
あなたはののClass.newInstance
Exception
で引数なしのコンストラクタによってスローラップしていないInvocationTargetException
という事実を使用することによりどのような場合にはこれを行うことができます。むしろそれは、それをスローします。の静かの
class ExUtil {
public static void throwSilent(Exception e) { //NOTICE NO THROWS CLAUSE
tl.set(e);
SilentThrower.class.newInstance(); //throws silently
}
private static ThreadLocal<Exception> tl = new ThreadLocal<Exception>();
private static class SilentThrower {
SilentThrower() throws Exception {
Exception e = tl.get();
tl.remove();
throw e;
}
}
}
次に、あなたはどこでも、このユーティリティを使用することができます:
ExUtil.throwSilent(new Exception());
//or
try {
ioMethod();
} catch (IOException e) { ExUtil.throwSilent(e); }
) - ところで、これはを本当に悪いアイデアのです
私は簡単にコードの任意のブロックをラップするためのEclipseの完了/テンプレートシステムを使用します。
ここに私のテンプレートです。
try { // Wrapp exceptions
${line_selection}${cursor}
} catch (RuntimeException e) { // Forward runtime exception
throw e;
} catch (Exception e) { // Wrap into runtime exception
throw new RuntimeException(
"Exception wrapped in #${enclosing_method}",
e);
}
soften(() -> methodThatMayThrow())
のJava 8で、それは同じくらい簡単です //iirekm.blogspot: