何时抛出IllegalStateException vs IllegalArgumentException?

时间:2018-02-11 20:50:34

标签: java exception illegalstateexception illegalargumentexception

让我们从Javadocs开始:

IllegalStateException

  

表示某个方法已被非法或不合适地调用   时间。换句话说,Java环境或Java应用程序不是   在适当的状态下进行所要求的操作。

IllegalArgumentException

  

抛出表示某个方法已被传递为非法或   不恰当的论点。

上述问题是它们非常黑白。考虑一种方法,其中方法正在解析调用者提供的文件。该文件存在,可读,格式正确。但是,文件中的某些内容不符合业务规则。抛出这种情况的适当例外是什么 - IllegalStateExceptionIllegalArgumentException

查看提供断言的各种库,例如Guava Preconditions或Spring Assert,似乎没有达成共识。有一些很好的讨论herehere,但没有一个能为我上面提到的常见用例提供确凿的答案。

免责声明:据我所知,我没有展示一些代码,但我认为这是一个特殊而实用的问题,需要考虑进行良好的API设计。让我们假装我们回到了堆栈溢出的好日子,当时人们乐于讨论实用问题,而不是低估任何看起来不像家庭作业的东西。

5 个答案:

答案 0 :(得分:6)

换句话说:

如果接受了类型而不是值,则会抛出IllegalArgumentException,例如期望正数并给出负数。

当一个方法被调用时,抛出IllegalStateException,就像从一个死线程调用一个方法一样。

我看不出它们如何混合。在你关于有问题的文件的问题中,我认为抛出ParseException或IOException会更合适。

答案 1 :(得分:2)

其他答案突出显示何时使用int count = 15; std::mutex mutex; void thread_1(void){ //Locks the mutex and unlocks when it goes out of scope std::lock_guard<std::mutex> guard(mutex); count = 0; x = count; count = x; } void thread_2(void){ //alternatively: mutex.lock() y = count; count = y; count = 0; mutex.unlock() } IllegalArgumentException。但在我看来(注意:基于意见)这些例外不应该用在你的用例中。

总结:某些文件包含有效格式的数据,已成功加载到应用程序中但某些值不符合您的业务规则(注意:没有IO操作失败,格式有效=&gt;既不{{1应该使用not IllegalStateException,它们表示IO操作失败或格式无效。)

为什么不应该使用IOException

抛出此异常表示方法已传递非法或不适当的参数。您可能会争辩说您有一个验证文件的方法,该字段的值或此文件中多个字段的值组合是非法的或不符合您的业务规则。 Yepp,指向你。但是,如果您在这种情况下抛出ParseException,则无法将IllegalArgumentException由其他库(或标准库或您自己的代码在其他地方)和您的IllegalArgumentException中的IllegalArgumentException分开验证器很容易指出业务规则违规(当然,您可以将IAE子类化并在调用方法中捕获它)。

为什么要分开这些例外?使用案例:应向用户显示违反业务规则的行为,以便他可以更改其不合规的输入。其他IAE或一般任何未捕获的运行时异常表示请求在服务器上失败,例如。在这些情况下,您必须向客户发送不同的回复。

您可以用类似的方式争论为什么不应该使用IllegalArgumentException来表示违反业务规则。那么,在您的用例中应该使用什么? 这在很大程度上取决于您的应用程序规模。 IllegalStateException的某些自定义子类可以为小型应用程序执行作业。对于较大的应用程序验证库,例如&#34; javax.validation&#34;值得一试。

答案 2 :(得分:1)

IllegalStateException用于编码错误,而不是输入错误。它违反了类的不变量,或者当对象处于错误状态时调用方法。示例使用封闭资源或关闭资源两次。

IllegalArgumentException是指每个方法API的参数值无效。当只允许正数时传递-1。

在这种情况下,两种例外都不合适。我会创建一个IOException的子类,因为输入文件中存在错误。

答案 3 :(得分:-1)

  

考虑一个用例......

如果这是我唯一的两个选择,在您的用例中,我倾向于IllegalStateException

为什么呢?因为参数有效,所以它们指向一个可以读取的文件。它不是无效的论据,而是解析文件会使状态无效。

这当然假设IllegalStateExceptionIllegalArgumentException是您正在考虑的唯一例外。

这当然只是MHO。我认为重要的一点是,您可以以一致的方式定义使用一个例外而不是另一个例外的原因,这使得您的API可以理解。

我也同意Saclyr(他们的答案为+1),您可以使用更合适的例外来定义方法调用失败的原因(个人而言,我考虑java.text.ParserException

答案 4 :(得分:-1)

我也认为这两种方法的语义非常接近。

根据IllegalArgumentException javadoc,可以通过抛出IllegalArgumentException来处理传递无效参数:

  

抛出表示某个方法已被传递为非法或   不恰当的论点。

但是调用带有错误参数的方法也可以通过抛出IllegalStateException来处理,因为它的javadoc声明:

  

表示某个方法已被非法或不合适地调用   时间。

实际上,调用带有不正确或非法参数的方法可能也意味着该方法是在非法或不适当的时间调用的。

为简单起见,我认为IllegalArgumentExceptionIllegalStateException可能会被一些开发人员以可互换的方式使用,因为问题是由传递的参数引起的。我在上面解释了什么 虽然IllegalStateException与传递参数无关的用例不能与IllegalArgumentException互换。

细微差别很小,大多数图书馆有时混合使用它们。

我害怕无法给你一个更可靠的解释。 语义是语义的,因为可以用更接近的方式解释两个事物,它通常没有被清楚地使用。