1

私は、基本的に 1 つの単純なことを実行し、エラー メッセージをログに記録し、同じエラー メッセージを使用して実行時例外をスローするメソッドを作成しています。RuntimeException の子例外をスローできるようにしたい。私が持っている方法は次のとおりです。

public static <T extends RuntimeException> void logErrorAndThrowException(Logger logger, String errorMessage, Class<T> exceptionClazz) throws T {
        logger.error(errorMessage);
        RuntimeException runtimeException = new RuntimeException(errorMessage);
        throw exceptionClazz.cast(runtimeException);   // Not work!!
    }

この例外を定義しました:

public final class MyException extends RuntimeException {
    public MyException() {
    }

    public MyException(String message) {
        super(message);
    }

    public MyException(Throwable cause) {
        super(cause);
    }

    public MyException(String message, Throwable cause) {
        super(message, cause);
    }
}

次に、次を使用してメソッドを呼び出します。

   logErrorAndThrowException(logger, "This is an error message", MyException.class);

上記のコメント行はキャスト例外で失敗します。次に、次の別の実装を試しました。

public static <T extends RuntimeException> void logWarningAndThrowException(Logger logger, String errorMessage, Class<T> exceptionClazz) throws T {
    logger.error(errorMessage);
    try {
        throw exceptionClazz.newInstance();
    } catch (InstantiationException e) {
        // handle
    } catch (IllegalAccessException e) {
        // handle
    }
}

この実装では、例外の引数なしのコンストラクタしか呼び出せないため、エラー メッセージを設定できません。

誰でもこれを手伝ってもらえますか?

4

2 に答える 2

5

インスタンス化する前に、まず例外クラスの適切なコンストラクターを取得する必要があります。あなたがするとき:

throw exceptionClazz.cast(runtimeException);   // Not work!!

あなたのクラスは のサブクラスであるため、これは機能しませんRuntimeException

できるよ:

final Constructor<T> c = exceptionClazz.getConstructor(String.class);
throw c.newInstance(theMessage);

しかし、実際には、そうしないでください。これら 2 つのリフレクション メソッドのすべての可能な例外に対処する必要があります...

リフレクションを含まない別の解決策は、次のようなインターフェースを持つことです。

public interface ExceptionCreator<T extends RuntimeException>
{
    T doException(String whatsWrong);
}

次に、次のものがありますIdentityHashMap

// IdentityHashMap because all Class objects are singletons
private static final Map<Class<? extends RuntimeException>, ExceptionCreator<?>> MAP
    = new IdentityHashMap<>;


// fill the map in a static initialization block

あなたの方法は次のようになります:

public static <T extends RuntimeException> void logErrorAndThrowException(Logger logger,     
    String errorMessage, Class<T> exceptionClazz) throws T
{
    logger.error(errorMessage);
    // Note: no checks for null here. If null, just throw a "plain" RuntimeException
    throw MAP.get(exceptionClazz).doException(errorMessage);
}
于 2013-06-14T07:57:44.437 に答える
1

スローせずに例外を作成できます。とにかくメソッドのクラスを知る必要があるため、RuntimeException をパラメーターとして直接使用します。ここでリフレクションを使用しようとしても意味がありません。

public static <T extends RuntimeException> void logErrorAndThrowException(Logger logger, T exception) throws T {
    logger.error(exception.getMessage());
    throw exception;   // works !!! ;-)
}
于 2013-06-14T08:34:20.983 に答える