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);

但是,真的,不要:你必须处理这两种反射方法的所有可能的例外......

另一种不涉及反射的解决方案是有一个接口,例如:

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 回答