声明方法引发未经检查的异常是否有好处?

2022-09-04 22:10:40

如果我有一个方法抛出一个未经检查的异常,例如:

void doSomething(int i) {
  if (i < 0) throw new IllegalArgumentException("Too small");
  // ...
}

显式声明该方法引发异常是否有任何好处,即

void doSomething(int i) throws IllegalArgumentException {
  if (i < 0) throw new IllegalArgumentException("Too small");
  // ...
}

与(或补充)描述javadoc中的行为相反:

/**
 * This method does something useful.
 * @param i some input value
 * @throws IllegalArgumentException if {@code i < 0}
 */
void doSomething(int i) {
  if (i < 0) throw new IllegalArgumentException("Too small");
  // ...
}

我声称拥有它们没有用的原因是:throws

  • throws没有提供关于将引发异常的情况的信息,仅提供可能引发异常的信息;
  • 因为它是一个未经检查的异常,所以我不会被迫在调用代码中处理异常。我只会真正知道,如果我去看看实施,它可能会被抛出doSomething;
  • 的正文可能会调用引发其他类型的未经检查的异常的代码;声称“这种方法投掷”似乎只是讲述了故事的一部分,可能;doSomethingIllegalArgumentException
  • 如果该方法是非最终的,则可以重写它,以便声明新实现以引发其他未经检查的异常;你不知道你调用的是哪个实现。

我声称拥有这些会很有用的原因是:throws

  • 它报告了您在调用该方法时可能合理预期会遇到的问题。

简而言之,我认为这是不必要的,但是通过javadoc描述是有用的。我很想知道其他人对此的看法。throws@throws


答案 1

如果您的API的用户看不到您的源代码,他就不会看到javadoc注释。这就是为什么声明该子句可能很有用的原因。throws

此外,对于一些程序员来说,从方法签名中快速确定异常比查看javadoc内部的内容更容易。

但总的来说,我认为仅在javadocs中列出未选中的异常更有用,因为如果子句中同时存在已选中和未选中的异常,则情况可能会令人困惑。如果不使用编译器或不查看每个异常类签名,则无法确定异常的类型。throws

但是,未经检查的异常意味着情况很严重,程序无法在运行时修复。如果您根据已检查异常的目的使用未选中的异常(您假设这种情况可以修复),但由于某种原因,您不希望编译器强制捕获异常,那么我建议将异常也放在子句中。throws


答案 2

当您声明某个方法为异常时,您正在对调用方说:throws

您有两种选择:

  1. 重新声明自己会引发相同的异常。
  2. 捕获异常并进行处理。

在案例1中,它可能会提醒用户实现一个 - 这可能是一个奖励。finally

在案例2中,它将注意力集中在异常上,这也可能是一个奖励。

如果您隐藏了这种可能性,则用户不会收到上述提醒。

对我来说,一个可能会不必要地混乱他们的代码,而另一个则保持甜蜜和简单。然而,一个鼓励专注于潜在的问题,而另一个可能会让你处于幸福的无知之中。

底线 - 问问自己,将异常声明为抛出会有多烦人(例如,你应该声明? - NO!),并且这种恼怒是否与将用户的注意力集中在,和上的好处相平衡。throws NullPointerExceptioncatchfinallythrows