4

我从代码开始。这个调用使用反射的方法

try {
    Method method = states.getClass().getDeclaredMethod(
            getCurrentStateId() + "_" + request.getEvent());
    states.setData(request, dataManager);
    method.invoke(states);
} catch (NoSuchMethodException e) {
    logger.debug("Method " + getCurrentStateId() + "_" + request.getEvent()
            + " cannot be found - invocation not performed.", e);
} catch (IllegalArgumentException e) {
    throw new InternalException("Method invocation with reflection failed.", e);
} catch (IllegalAccessException e) {
    throw new InternalException("Method invocation with reflection failed.", e);
} catch (InvocationTargetException e) {
    throw new InternalException("Method invocation with reflection failed.", e);
}

并使用以下代码调用该方法,该代码抛出PropertiesDontMatchException(运行时)。

...
if (totalCredits < minimumCredits || totalCredits > maximumCredits) {
    throw new PropertiesDontMatchException("Minimum amount of credits=" + minimumCredits
            + ", maximum amount of credits=" + maximumCredits + ". Your amount of credits="                 + totalCredits + ". You have to modify your set of subjects.");
}
...

问题是我的运行时异常被包装到InvocationTargetException第一个代码片段中并被捕获。这不是我想要的。但是根据文档,这是正确的行为。

所以我想出了这个解决方案

...
} catch (InvocationTargetException e) {
    if (e.getCause() instanceof PropertiesDontMatchException) {
        throw (PropertiesDontMatchException) e.getCause();
    }
    throw new InternalException("Method invocation with reflection failed.", e);
}
...

这是传播我的运行时异常的正确方法还是有更好的解决方案?

4

1 回答 1

4

是的,在这种情况下,这是正确的错误处理。我只会将您的测试扩展到任何RuntimeException

} catch (InvocationTargetException e) {
    if (e.getCause() instanceof RuntimeException) {
        throw (RuntimeException) e.getCause();
    }
    if (e.getCause() instanceof Error) {
        throw (Error) e.getCause();
    }
    throw new InternalException("Method invocation with reflection failed.", e);
}

或者,如果您不介意使用而不是自定义检查异常,请使用来自Throwables实用程序类:RuntimeExceptionInternalException

} catch (InvocationTargetException e) {
    throw Throwables.propagate(e.getCause());
}

额外的包装是必要的,以区分您的方法抛出IllegalAccessException和反射机制本身抛出它。

可以观察到类似的 API 设计选择Future.get()- 如果从异步作业抛出异常,ExecutionException则抛出包装实际异常。

于 2012-04-13T20:44:10.897 回答