捕获多个异常并重新抛出一个通用异常

7
我正在使用反射将一些数据添加到第三方库中的类的私有变量中。在此过程中,可能会抛出约四种不同的异常,所有这些异常都与反射相关,而且都很少发生。我正在硬编码涉及的类和变量名称。除非该库升级并发生了重大变化,否则我不太可能收到任何类未找到或字段未找到错误。
我不想为我的调用者声明这四个异常中的所有异常。他很可能永远不会看到它们。我想捕获所有这些异常并抛出另一个异常,以表明“发生了Java反射错误;很可能是库已升级并以与此方法不兼容的方式进行了更改。”是否有标准的Java异常可以抛出,指示一般的反射错误?我应该定义自己的异常吗?还是最好声明此方法可以抛出所有可能的反射异常?
6个回答

6

我通常会问自己以下问题:

  • 调用该方法的人是否可以针对这些不同的异常类型进行不同处理?
  • 还是他们会将它们都视为一样的处理呢?
  • 调用者/用户是否能够从这个错误中恢复过来?

如果调用代码很可能将这四个异常视为相同的(即无法恢复的错误),那么捕获每个异常并重新抛出一个更一般的(单一的)异常绝对是有意义的。如果这样做,确保将生成的异常作为内部异常附加,以帮助任何端口的调试或故障排除。


2

关于已检查异常和未检查异常存在一些争议。个人认为,已检查异常是Java中最糟糕的想法--但这只是一个观点(然而我并不是唯一这么想的人)

无论如何,我认为重要的事情是将它们改为单个未检查异常。往往我使用像IllegalStateException或IllegalParameterException这样的单个异常--配合清晰的文本描述,这两个异常可以覆盖90%的方法可能出现的问题。


2

首先,除非你确实有必要使用反射,否则不要使用它,因为它是邪恶的。假设你确实需要使用:

由于你正在硬编码所有名称,因此只剩下Method.invokeConstructor.newInstanceField.get/set。我建议只将你可以处理的已检查异常包装在Error中重新抛出。它们不应该发生,如果你想处理它,我建议在类初始化时进行检查。当然,InvocationTargetException应该被解包并以适当的方式处理(对于方法/构造函数没有声明的已检查异常,抛出一个包装的Error)。


2

如果您从未预期发生异常,可以将所有异常转换为AssertionError。 如果您想处理特定异常,则可以解包InvocationTargetException。 如果您想抛出方法实际抛出的异常而不是InvocationTargetException,则可以使用此技巧,但可能会更加混乱。

} catch (InvocationTargetException e) {
    // Throw any exception in the current thread (even if it is a checked exception)
    Thread.currentThread().stop(e.getCause());
}

1
为什么不直接抛出 e.getCause()?使用 Thread.stop() 过度且已经被弃用。 - matt b
1
你试过了吗?e.getCause() 返回一个Throwable。如何抛出一个Throwable而不必声明它? - Peter Lawrey

1

将那些异常类扩展自GeneralException,然后捕获那个GeneralException,这个怎么样?

我现在就试试!:)


这个完美地运作了!希望能够帮助到有同样问题的人! - Fabio Milheiro

0

我认为在这种情况下声明异常没有意义。 因此,我会从反射中捕获异常,可能记录堆栈跟踪,并抛出一些RuntimeException,它的优点是不需要声明。 如果你懒得声明,你可以只使用带有适当消息的RuntimeException。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接