【问题标题】:What's wrong with throwing multiple checked exceptions in Java?在 Java 中抛出多个已检查异常有什么问题?
【发布时间】:2017-03-25 04:59:55
【问题描述】:

考虑下面的 Java 代码 sn-p:

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,但是为什么在这种情况下在这里捕获一个并将另一个传递到堆栈而不是将它们都传递到堆栈以供其他东西处理它们会更好?

【问题讨论】:

  • 这确实是基于意见的,但我认为这样做没有任何问题。如果我使用 SonarLint,我会关闭该警告。

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


【解决方案1】:

此建议的基础是什么最佳实践?

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

为什么在这种情况下,在这里捕获一个并将另一个向上传递到堆栈而不是将它们都向上传递给其他东西来处理它们会更好?

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

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

但与之相反的论点是,当您统一抛出列表时,您正在向程序员/编译器隐藏信息。例如,如果 API 更改为:

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

使用该 API 的程序员不再知道哪些类型的反射操作异常会被抛出。而当你通过捕获、包装和抛出一个新异常来“统一”时,情况会更糟。

请注意,我并不是说这两种方法都是错误的。我要说的是上下文应该决定你采取哪种方法。换句话说,诉诸“最佳实践”是没有意义的。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:
      public class IllegalAccessException
      extends ReflectiveOperationException
      

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

      【讨论】:

      • 这是对此处未提出的其他问题的一个很好的回答。
      猜你喜欢
      • 2016-07-14
      • 2013-01-16
      • 1970-01-01
      • 2016-01-22
      • 2019-03-04
      • 2016-10-16
      • 1970-01-01
      • 1970-01-01
      • 2016-05-13
      相关资源
      最近更新 更多