什么时候应该抛出IllegalArgumentException?

我担心这是一个运行时exception,所以应该谨慎使用它。
标准用例:

void setPercentage(int pct) { if( pct < 0 || pct > 100) { throw new IllegalArgumentException("bad percent"); } } 

但是,似乎这将迫使下面的devise:

 public void computeScore() throws MyPackageException { try { setPercentage(userInputPercent); } catch(IllegalArgumentException exc){ throw new MyPackageException(exc); } } 

重新成为检查的exception。

好吧,让我们一起去。 如果你input错误,你会得到一个运行时错误。 所以首先这是一个相当困难的政策来统一实施,因为你可能需要做相反的转换:

 public void scanEmail(String emailStr, InputStream mime) { try { EmailAddress parsedAddress = EmailUtil.parse(emailStr); } catch(ParseException exc){ throw new IllegalArgumentException("bad email", exc); } } 

更糟糕的是,在检查0 <= pct && pct <= 100 ,客户端代码可能会静态执行,但对于更高级的数据(例如电子邮件地址),或者更糟糕的情况,并非如此,必须对数据库进行检查,因此一般客户端代码不能预先validation。

所以基本上我说的是我没有看到使用IllegalArgumentException的有意义的一致的策略。 看起来不应该使用,我们应该坚持我们自己的检查exception。 什么是好的用例来抛出这个?

IllegalArgumentException的api文档是:

抛出以指示某个方法已通过非法或不恰当的参数。

从看如何在jdk库中使用它 ,我会说:

  • 这似乎是一个防御性的措施,抱怨input显然是不好的input可以进入工作,并导致一些失败的中途通过一个无意义的错误信息。

  • 它用于抛出一个检查exception太烦人的情况(虽然它在java.lang.reflect代码中出现,关于检查exception抛出的荒谬级别的关注并不明显)。

我会使用IllegalArgumentException为通用工具(试图保持与jdk用法保持一致)进行最后的防御性的参数检查,期望的是一个坏的参数是程序员错误,类似于NPE。 我不会用它来在业务代码中实现validation。 我当然不会使用它的电子邮件的例子。

当谈到“糟糕的input”时,你应该考虑input来自哪里。

是由用户或其他外部系统input的input是不受控制的,您应该期望input无效,并始终对其进行validation。 在这种情况下抛出一个检查的exception是完全可以的。 您的应用程序应通过向用户提供错误消息来从此exception中“恢复”。

如果input来自你自己的系统,比如你的数据库,或者你的应用程序的其他部分,你应该可以依赖它来生效(应该在它到达之前validation它)。 在这种情况下,抛出一个像IllegalArgumentException这样的不被检查的exception是完全可以的,这个exception不应该被捕获(通常你​​不应该捕获未经检查的exception)。 这是一个程序员的错误,无效值到达那里;)您需要修复它。

“谨慎”抛出运行时exception并不是一个很好的策略 – 有效的Javabuild议您在合理预期调用者可以恢复时使用已检查的exception。 (程序员错误是一个具体的例子:如果一个特定的情况表明程序员错误,那么你应该抛出一个未经检查的exception;你希望程序员有一个逻辑问题出现的堆栈跟踪,而不是尝试自己处理它。

如果没有恢复的希望,那么可以随意使用未经检查的exception; 抓住他们没有意义,所以这很好。

尽pipe从你的例子中不能100%清楚这个例子在你的代码中。

任何API在执行之前都应该检查任何公共方法的每个参数的有效性:

 void setPercentage(int pct, AnObject object) { if( pct < 0 || pct > 100) { throw new IllegalArgumentException("pct has an invalid value"); } if (object == null) { throw new IllegalArgumentException("object is null"); } } 

它们代表了应用程序中99.9%的时间错误,因为它要求不可能的操作,所以最后它们是应该使应用程序崩溃的错误(所以这是一个不可恢复的错误)。

在这种情况下,在快速失败的方法之后,应该让应用程序完成以避免损坏应用程序状态。

正如在oracle官方教程中指出的那样,它指出:

如果客户可以合理预期从exception中恢复,请将其作为检查exception。 如果客户端无法做任何事情来恢复exception,使其成为一个unchecked例外。

如果我有一个使用JDBC与数据库交互的应用程序,并且我有一个方法将参数作为int itemdouble price 。 相应项目的price从数据库表中读取。 我只是将购买的item总数与price值相乘并返回结果。 虽然我总是很确定(应用程序结束时)表格中的价格字段值永远不会是负值,但如果价格值出现负值呢? 这表明数据库方面存在严重的问题。 也许是运营商input错误的价格。 这是调用该方法的应用程序的其他部分无法预料并且无法从中恢复的问题。 这是数据库中的一个BUG 。 所以,在这种情况下,应该抛出IllegalArguementException() ,它会声明the price can't be negative
我希望我已经明确expression了我的观点。