Java:编写一个引发任何RuntimeException的通用方法

Java:编写一个引发任何RuntimeException的通用方法,java,generics,log4j,Java,Generics,Log4j,我正在编写一个方法,它基本上只做一件简单的事情,记录错误消息并使用相同的错误消息引发运行时异常。我希望它能够抛出RuntimeException的任何子异常。我得到的方法是: public static <T extends RuntimeException> void logErrorAndThrowException(Logger logger, String errorMessage, Class<T> exceptionClazz) throws T {

我正在编写一个方法,它基本上只做一件简单的事情,记录错误消息并使用相同的错误消息引发运行时异常。我希望它能够抛出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!!
    }
然后,我使用以下命令调用该方法:

   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
    }
}
使用此实现,我只能调用异常的no-arg构造函数,因此无法设置错误消息


有人能帮上忙吗?

在实例化异常类之前,首先需要为它获取适当的构造函数。当您这样做时:

throw exceptionClazz.cast(runtimeException);   // Not work!!
这无法工作,因为您的类是RuntimeException的子类

你可以做:

final Constructor<T> c = exceptionClazz.getConstructor(String.class);
throw c.newInstance(theMessage);
你的方法是:

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

在实例化异常类之前,首先需要为它获取适当的构造函数。当您这样做时:

throw exceptionClazz.cast(runtimeException);   // Not work!!
这无法工作,因为您的类是RuntimeException的子类

你可以做:

final Constructor<T> c = exceptionClazz.getConstructor(String.class);
throw c.newInstance(theMessage);
你的方法是:

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

您可以创建一个异常而不抛出它。因为您无论如何都需要知道方法的类,所以直接使用RuntimeException作为参数。在这里尝试使用反射毫无意义

public static <T extends RuntimeException> void logErrorAndThrowException(Logger logger, T exception) throws T {
    logger.error(exception.getMessage());
    throw exception;   // works !!! ;-)
}

您可以创建一个异常而不抛出它。因为您无论如何都需要知道方法的类,所以直接使用RuntimeException作为参数。在这里尝试使用反射毫无意义

public static <T extends RuntimeException> void logErrorAndThrowException(Logger logger, T exception) throws T {
    logger.error(exception.getMessage());
    throw exception;   // works !!! ;-)
}

如果您将方法声明为抛出E,那么您可以让它抛出E1、E2等,它们是E的子类。不幸的是,异常和泛型不能很好地混合…更标准的解决方案,因此,对其他人来说更容易理解等等,就是将异常包装为一个原因:抛出新的RuntimeExceptionmyException。这避免了上述问题,并保留原始异常的堆栈跟踪,而不仅仅是消息,这通常有助于调试。如果您将方法声明为抛出E,则可以使其抛出E1、E2等E的子类。不幸的是,异常和泛型不能很好地混合…更标准的解决方案,因此,其他人更容易理解的是将异常包装为原因:抛出新的RuntimeExceptionmyException。这避免了上述问题,并保留了原始异常的堆栈跟踪,而不仅仅是消息,这通常有助于调试。这是我想到的解决方案。这看起来很复杂,你确定不能在要记录错误的地方创建异常吗?@kutschkem不是我的选择,OP的;我只是针对所表达的需求给出了一个可能的解决方案;这就是我想到的解决方案。这看起来很复杂,你确定你不能只在你想记录错误的地方创建异常吗?@kutschkem不是我的选择,OP的;我只是针对所表达的需求给出了一个可能的解决方案;