22

私はこのような方法を持っています:

public void getSomething(){
...
}

Exceptionインサイドを投げたいgetSomething()Exception私のメソッドがそこにスローされることを許可していないため、コンパイラはそれを許可しません。Exceptionしかし、テスト用にのサブクラスをスローする必要があります( Unchecked をスローすることはできませんException)。これは明らかにハックですが、テストには必要です。EasyMock を試しましたが、それもできません。それを行う方法はありますか?

ありがとう、ショーン・グエン

4

3 に答える 3

26

方法 1:

Alexey Ragozin によるこの投稿では、ジェネリック トリックを使用して宣言されていないチェック済み例外をスローする方法について説明しています。その投稿から:

public class AnyThrow {

    public static void throwUnchecked(Throwable e) {
        AnyThrow.<RuntimeException>throwAny(e);
    }

    @SuppressWarnings("unchecked")
    private static <E extends Throwable> void throwAny(Throwable e) throws E {
        throw (E)e;
    }
}

トリックは、型がへの呼び出しでthrowUncheckedあるというコンパイラへの「嘘」に依存しています。は として宣言されているため、コンパイラは、特定の呼び出しが単に をスローできると考えます。もちろん、任意に宣言してやみくもにキャストすることでこのトリックが可能になり、呼び出し元が引数のキャスト先を決定できるようになります。実行時には消去され、意味がありません。ERuntimeExceptionthrowAnythrowAnythrows ERuntimeExceptionthrowAnyEE

あなたが指摘したように、そのようなことを行うことは巨大なハックであり、その使用法を非常によく文書化する必要があります.


方法 2:

この目的のためにも使用できますsun.misc.Unsafe。最初に、リフレクションを使用してそのクラスのインスタンスを返すメソッドを実装する必要があります。

private static Unsafe getUnsafe() {
    try {
        Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafeField.setAccessible(true);
        return (Unsafe)theUnsafeField.get(null);
    }
    catch (NoSuchFieldException e) {
        throw new RuntimeException(e);
    }
    catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

呼び出しUnsafe.getUnsafe()は通常SecurityException. のインスタンスをUnsafe取得したら、その恐ろしい機能を使用できます。

Unsafe unsafe = getUnsafe();
unsafe.throwException(new Exception());

クレジットは、投稿https://stackoverflow.com/questions/5574241/interesting-uses-of-sun-misc-unsafeのこの回答に送られます。完全を期すためにこれについて言及したいと思いましたが、コードに許可するのではなく、上記のトリックを使用する方がおそらく良いでしょう.Unsafe


方法 3:

usingに関するリンクされた回答のコメントでUnsafe、 @bestsssは非推奨の method を使用したはるかに簡単なトリックを指摘しThread.stop(Throwable)ています。

Thread.currentThread().stop(new Exception());

この場合、@SuppressWarnings("deprecation")非常に激しく文書化します。繰り返しますが、私は (相対的な) 清潔さのために最初のトリックを好みます。

于 2012-08-13T22:20:01.447 に答える
5

Java には、チェック済みと未チェックの 2 種類の例外があります。チェックされた例外を宣言する必要がありますが、チェックされていない例外を宣言する必要はありません。

RuntimeException基本的な未チェックの例外であるため、宣言せずにスローできます。

public void getSomething(){
   throw new RuntimeException("I don't have to be declared in the method header!");
}

補足として、生の RuntimeException をスローするのはおそらく望ましくありませんが、必要に応じてより具体的なものにサブクラス化してください。RuntimeException のサブクラスもチェックされません。

于 2012-08-13T22:03:01.700 に答える