在Java中抛出多个已检查的异常有什么问题?

时间:2017-03-25 04:59:55

标签: java exception sonarlint checked-exceptions sonarlint-eclipse

考虑下面的Java代码片段:

public <T> T create(Class<T> clazz) throws InstantiationException, IllegalAccessException {
    return clazz.newInstance();
}

这在Eclipse(Neon.2,JDK 8)中使用SonarLint执行静态代码分析。它提供了重构的建议:

  

重构此方法以抛出最多一个已检查的异常,而不是:java.lang.InstantiationException,java.lang.IllegalAccessException

此建议的基础是什么最佳做法?我理解一般有一些关于已检查异常的controversy,但为什么在这个实例中捕获一个并将另一个传递到堆栈而不是将它们传递到堆栈中为什么会更好处理它们?

3 个答案:

答案 0 :(得分:2)

我同意@David这是基于意见的,但在我看来,最好的做法是从基于单一责任原则的方法中抛出一个例外。当抛出多个异常时,听起来该方法被实现为执行多个任务,尽管我们每个人都经常这样做,但这并不是一个理想的做法。当有这样的需求时,最好通过使用适当的错误代码或错误消息提出问题来抛出自定义异常

答案 1 :(得分:2)

  

此建议的基础是什么最佳做法?

“最佳实践”意味着对该问题有一个客观正确的答案。没有一个。

  

为什么在这个实例中捕获一个并将另一个传递到堆栈而不是将它们传递到堆栈以获得其他东西来处理它们会更好?

在这种情况下,你不会这样做。 IllegalAccessExceptionInstantiationException都是ReflectiveOperationException的子类型。如果您想将签名减少到单个已检查的异常(如检查器所示),您将使用该异常。

通常,统一(通过选择现有的超类或通过重新设计异常层次结构)的参数是调用者需要处理更少的异常。

但反驳的是,当你统一抛出列表时,你正在隐藏程序员/编译器的信息。例如,如果API已更改为:

public <T> T create(Class<T> clazz) throws ReflectiveOperationException {
    ...
}

使用该API的程序员不再知道可以抛出哪种反射操作异常。当你通过捕捉,包裹和投掷作为一个新例外来“统一”时,情况会更糟。

请注意,我并不是说这两种方法都是错误的。我所说的是上下文应该决定你采取哪种方法。换句话说,对“最佳实践”的吸引力忽略了这一点。

答案 2 :(得分:-1)

public class IllegalAccessException
extends ReflectiveOperationException

当应用程序尝试反射创建实例(不是数组),设置或获取字段或调用方法时,抛出IllegalAccessException,但当前正在执行的方法无法访问定义指定的类,字段,方法或构造函数。