IllegalStateException 的预期用途是什么?

2022-08-31 13:03:00

这是在今天与一位同事的讨论中提出的。

Javadocs for Java's IllegalStateException 指出:

在非法或不适当的时间调用方法的信号。换句话说,Java 环境或 Java 应用程序未处于适合所请求操作的状态。

有效的Java说(项目60,第248页):

另一个经常被重用的例外是 IllegalStateException。如果由于接收对象的状态而调用是非法的,则这通常是要引发的异常。例如,如果调用方在正确初始化某个对象之前尝试使用该对象,则将引发异常。

这里似乎有一点差异。javadocs的第二句话听起来像是异常可以描述关于Java执行状态的非常广泛的条件,但是有效Java中的描述使它听起来像是用于专门与调用其方法的对象的状态状态相关的条件。

我在JDK(例如集合)和番石榴中看到的用法似乎绝对属于有效Java所谈论的类别(“此对象处于无法调用此方法的状态”)。这似乎也与 的兄弟姐妹一致。MatcherIllegalStateExceptionIllegalArgumentException

JDK 中是否有任何与“Java 环境”或“Java 应用程序”相关的合法用法?或者是否有任何最佳实践指南主张将其用于更广泛的执行状态?如果不是,为什么javadocs是这样说的?;)IllegalStateException


答案 1

以下是JDK中此异常的一个特别合法的用法(请参阅:URLConnection.setIfModifiedSince(long)中的300多个其他用法:

public void setIfModifiedSince(long ifmodifiedsince) {
    if (connected)
        throw new IllegalStateException("Already connected");
    ifModifiedSince = ifmodifiedsince;
}

我认为这个例子很清楚。如果对象处于特定状态(“已连接”),则不应调用某些操作。在这种情况下,当建立连接时,无法设置某些属性。

当您的类具有某些状态(状态机?)随时间而变化,使某些方法变得无关紧要或不可能时,此异常特别有用。考虑一个具有 和 方法的类。虽然一个接一个地打电话两次,可能没什么错,但为启动的汽车加油肯定是一个坏主意。也就是说 - 汽车处于错误状态。Carstart()stop()fuel()start()

可以说,好的API不应该允许我们调用错误状态的方法,以便在编译时发现这样的问题,而不是在运行时。在此特定示例中,连接到 URL 应返回具有不同对象以及方法子集,所有这些方法在连接后均有效。


答案 2

下面是 JDK 中的一个示例。有一个名为java.lang.Shutdown的包私有类。如果系统正在关闭,并且您尝试添加新的挂钩,它将引发 IllegalStateException。有人可能会争辩说这符合“javadoc”指南的标准 - 因为Java环境处于错误状态。

class Shutdown {    
...

   /* Add a new shutdown hook.  Checks the shutdown state and the hook itself,
    * but does not do any security checks.
    */
    static void add(int slot, Runnable hook) {
        synchronized (lock) {
            if (state > RUNNING)
                throw new IllegalStateException("Shutdown in progress");

            if (hooks[slot] != null)
                throw new InternalError("Shutdown hook at slot " + slot + " already registered");

            hooks[slot] = hook;
        }
    }

然而,这也说明了“javadoc”指南和“有效Java”指南之间确实没有区别。由于实现关机的方式,JVM 的关机性存储在一个名为 state 的字段中。因此,它还符合有关何时使用 IllegalStateException 的“有效 Java”指南,因为“state”字段是接收对象状态的一部分。由于接收对象(Shutdown)处于错误状态,因此它会引发 IllegalStateException。

在我看来,关于何时使用TravilStateException的两种描述是一致的。有效的Java描述更实用一些,仅此而已。对于我们大多数人来说,整个Java环境中最重要的部分是我们现在正在编写的类,所以这就是作者所关注的。