什么时候应该抛出非法争议异常?

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

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

但这似乎会强制进行以下设计:

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

使其恢复为已检查的异常。

好吧,但是让我们继续吧。如果输入错误,则会收到运行时错误。因此,首先,这实际上是一个相当难以统一实施的策略,因为您可能必须执行完全相反的转换:

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

因此,基本上我要说的是,我没有看到一个有意义的一致策略来使用.似乎不应该使用它,我们应该坚持我们自己的检查例外。抛出这个的好用例是什么?IllegalArgumentException


答案 1

用于以下各项的 API 文档:IllegalArgumentException

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

JDK库中如何使用它来看,我会说:

  • 在输入进入工作状态并导致某些内容在中途失败并带有荒谬的错误消息之前,抱怨明显错误的输入似乎是一种防御措施。

  • 它用于抛出检查异常太烦人的情况(尽管它在java.lang.reflect代码中出现,其中对检查异常引发的荒谬级别的担忧并不明显)。

我会用来对常用实用程序进行最后的防御性参数检查(试图与JDK用法保持一致)。或者,如果期望是一个糟糕的参数是程序员错误,类似于 .我不会用它来在业务代码中实现验证。我当然不会将其用于电子邮件示例。IllegalArgumentExceptionNullPointerException


答案 2

在谈论“不良输入”时,您应该考虑输入来自何处。

输入是由用户或其他您无法控制的外部系统输入的,您应该期望输入无效,并始终对其进行验证。在这种情况下,完全可以抛出已检查的异常。应用程序应通过向用户提供错误消息来“恢复”此异常。

如果输入来自您自己的系统,例如您的数据库或应用程序的其他一些部分,您应该能够依赖它来使其有效(它应该在到达那里之前已经过验证)。在这种情况下,抛出一个未经检查的异常是完全可以的,比如一个 IllegalArgumentException,它不应该被捕获(通常你不应该捕获未经检查的异常)。程序员的错误是,无效值首先到达那里;)您需要修复它。