声明方法是否会抛出未经检查的exception是否有优势?

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

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

明确声明该方法抛出exception是否有任何好处,即

 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没有提供关于抛出exception的情况的信息,只提供它可能被抛出的信息;
  • 因为它是一个未经检查的exception,所以我不会被迫在调用代码时处理exception。 我只会真的知道如果我去看看doSomething的实现可能会被抛出;
  • doSomething的主体可能会调用抛出其他类型的未经检查的exception的代码; 声称’此方法抛出IllegalArgumentException ‘似乎只是告诉了故事的一部分,可能;
  • 如果该方法是非final的,则可以重写它,以便声明新的实现抛出额外的未经检查的exception; 你不知道你正在调用哪个实现。

我之所以声称它的原因是有用的是throws

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

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

当您声明某个方法throwsexception时,您要对调用者说:

你有两个选择:

  1. 将自己视为抛出相同的exception。
  2. 抓住exception并处理它。

在案例1中,它可以提醒用户实现finally – 这可能是奖励。

在案例2中,它将思想集中在exception上,这也可能是一个奖励。

如果您隐藏了这种可能性,则上述提醒都不会发生在用户身上。

对我来说,一个人可能会不必要地混乱他们的代码,而另一个人保持它的甜蜜和简单。 然而,一个人鼓励关注潜在的问题而另一个人可能会让你陷入幸福的无知状态。

底线 – 问问自己如何将exception声明为抛出是多么令人恼火(例如,你应该声明throws NullPointerException吗? – 不!)并且这种烦恼是通过将用户的注意力集中在catchfinallythrows的优点来平衡的。

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

一些程序员更容易从方法签名中快速确定exception,而不是查看javadoc中的内容。

但总的来说,我认为仅在javadocs中列出未经检查的exception更有用,因为如果throws子句中存在checked和uncheckedexception,则情况可能会令人困惑。 没有编译器或没有查看每个exception类签名,您无法确定exception的类型。

然而,未经检查的exception意味着情况是关键的,并且程序无法在运行时修复。 如果你通过检查exception的目的使用未经检查的exception(你假设情况可以修复)但由于某种原因你不希望编译器强制捕获exception,那么我建议将exception放在throws子句中。

例外用于报告3种问题:

  • JVM和低级运行时环境的问题。
  • 检测到逻辑错误(错误)。
  • 程序员在尝试操作之前无法预测的运行时问题。

前两种可能在任何时候发生,并且基本上没有好的方法来处理它们。 所以抓住它们没有意义,因此通过在throws条款中声明它们来记录它们没有意义。 第三种是您希望客户了解和处理的那种。 对于那些,您希望清楚地记录可能抛出exception,暗示调用代码必须准备好通过捕获它或正确传播它来处理exception。 您可以使用throws子句来执行此操作。

现在,对我而言,似乎很清楚Java语言设计者打算检查exception,并且仅检查exception,以用于第三种类型。 如果总是这样,那么对你的问题的简单回答就是,不,不要在throws子句中声明未经检查的exception。

但是有一个复杂的问题。 现在很常见 (由Spring推广)以避免第三种类型的已检查exception,并且几乎在所有情况下都使用未经检查的exception。 如果您使用该样式进行编程,则使用throws子句声明未经检查的exception可能会有所帮助。