简体   繁体   English

IllegalStateException的用途是什么?

[英]What's the intended use of IllegalStateException?

This came up in a discussion with a colleague today. 今天与同事讨论了这个问题。

The Javadocs for Java's IllegalStateException state that it: Javadocs for Java的IllegalStateException声明它:

Signals that a method has been invoked at an illegal or inappropriate time. 表示在非法或不适当的时间调用了方法。 In other words, the Java environment or Java application is not in an appropriate state for the requested operation. 换句话说,Java环境或Java应用程序未处于所请求操作的适当状态。

And Effective Java says (Item 60, page 248): 而Effective Java则说(项目60,第248页):

Another commonly reused exception is IllegalStateException. 另一个常用的异常是IllegalStateException。 This is generally the exception to throw if the invocation is illegal because of the state of the receiving object. 如果由于接收对象的状态而调用是非法的,则通常会抛出异常。 For example, this would be the exception to throw if the caller attempted to use some object before it had been properly initialized. 例如,如果调用者在正确初始化之前尝试使用某个对象,则抛出此异常。

It seems there's a bit of discrepancy here. 看来这里有一点差异。 The second sentence of the javadocs makes it sound like the exception could describe a very broad condition about the Java execution state, but the description in Effective Java makes it sound like it's used for conditions related specifically to the state of the state of the object whose method has been called. javadocs的第二句使得听起来像异常可以描述关于Java执行状态的非常宽泛的条件,但是Effective Java中的描述使得它听起来像是用于特定于与对象的状态状态相关的条件。方法已被调用。

The usages I've seen in the JDK (eg collections, Matcher ) and in Guava definitely seem to fall into the category that Effective Java talks about ("This object is in a state where this method can't be called"). 我在JDK(例如集合, Matcher )和Guava中看到的用法肯定似乎属于Effective Java谈论的类别(“此对象处于无法调用此方法的状态”)。 This also seems consistent with IllegalStateException 's sibling IllegalArgumentException . 这似乎与IllegalStateException的兄弟IllegalArgumentException一致。

Are there any legitimate IllegalStateException usages in the JDK that do relate to the "Java environment" or "Java application"? JDK中是否存在与“Java环境”或“Java应用程序”相关的合法IllegalStateException用法? Or do any best practices guides advocate using it for the broader execution state? 或者是否有任何最佳实践指南主张将其用于更广泛的执行状态? If not, why the heck are the javadocs phrased like that? 如果没有,为什么这样的javadocs就像那样? ;) ;)

Here is one particularly legitimate usage of this exception in JDK (see: URLConnection.setIfModifiedSince(long) among 300+ other usages of it: 这是JDK中这个异常的一个特别合法的用法(参见: URLConnection.setIfModifiedSince(long)在300多个其他用法中:

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

I think the example is pretty clear. 我认为这个例子很清楚。 If the object is in particular state (" Already connected "), some operations should not be called. 如果对象处于特定状态(“ 已连接 ”),则不应调用某些操作。 In this case when connection was established, some properties cannot be set. 在这种情况下,建立连接时,无法设置某些属性。

This exception is especially useful when your class has some state (state machine?) that changes over time, making some methods irrelevant or impossible. 当您的类具有随时间变化的某些状态(状态机?)时,此异常特别有用,使某些方法无关紧要或不可能。 Think about a Car class that has start() , stop() and fuel() methods. 想想具有start()stop()fuel()方法的Car类。 While calling start() twice, one after another, is probably nothing wrong, but fueling a started car is certainly a bad idea. 虽然一次又一次地调用start()两次,但可能并没有错,但是为一辆已启动的汽车加油肯定是一个坏主意。 Namely - car is in a wrong state. 即 - 汽车处于错误状态。

Arguably good API should not allow us to call methods in wrong state so that problems like that are discovered at compile time, not at runtime. 可以说好的API不应该允许我们在错误的状态下调用方法,以便在编译时发现类似的问题,而不是在运行时。 In this particular example connecting to a URL should return a different object with a subset of methods, all of which are valid after connecting. 在此特定示例中,连接到URL应返回具有方法子集的不同对象,所有这些方法在连接后都有效。

Here is an example in the JDK. 这是JDK中的一个示例。 There is a package private class called java.lang.Shutdown. 有一个名为java.lang.Shutdown的包私有类。 If the system is shutting down and you attempt to add a new hook, it throws the IllegalStateException. 如果系统正在关闭并且您尝试添加新挂钩,则会抛出IllegalStateException。 One could argue that this meets the criteria of the "javadoc" guidance - since it is the Java environment that is in the wrong state. 有人可能会说这符合“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;
        }
    }

However it also illustrates that there really is no distinction between the "javadoc" guidance and the "Effective Java" guidance. 然而,它也说明了“javadoc”指南和“Effective Java”指南之间没有区别。 Because of the way Shutdown is implemented, the shutdown-ness of the JVM is stored in a field called state. 由于实现Shutdown的方式,JVM的shutdown-ness存储在一个名为state的字段中。 Therefore it also meets the "Effective Java" guidance for when to use IllegalStateException, since the "state" field is part of the state of the receiving object. 因此,它还满足何时使用IllegalStateException的“Effective Java”指南,因为“state”字段是接收对象状态的一部分。 Since the receiving object (Shutdown) is in the wrong state, it throws the IllegalStateException. 由于接收对象(Shutdown)处于错误状态,因此会抛出IllegalStateException。

In my opinion the two descriptions of when to use IllegalStateException are consistent. 在我看来,何时使用IllegalStateException的两个描述是一致的。 The Effective Java description is a bit more practical, that's all. 有效的Java描述更实用,就是这样。 For most of us, the most important part of the entire Java environment is the class that we are writing right now, so that is what the author is focusing on. 对于我们大多数人来说,整个Java环境中最重要的部分是我们现在正在编写的类,因此这是作者关注的内容。

I guess if you see usage of IllegalStateException I would say second if more appropriate. 我想如果你看到使用IllegalStateException我会说第二个更合适。 This exception is used in lot of packages 许多包都使用此异常

  • java.net java.net
  • java.nio java.nio中
  • java.util java.util中
  • java.util.concurrrent etc java.util.concurrrent等

To specify one example ArrayBlockingQueue.add throws this exception if queue is already full. 要指定一个示例,如果队列已满,则抛出此异常ArrayBlockingQueue.add Now full is state of the object and it is being invoked at inappropriate or Illegal time 现在已满是对象的状态,并且在不适当或非法时间调用它

I guess both means same but difference of wording. 我想两者都意味着相同但措辞不同。

Given a library, it should throw an IllegalStateException or IllegalArgumentException whenever it detects a bug due to the user code, whereas the library should throw an AssertionError whenever it detects a bug due to the library's own implementation. 给定一个库,每当它检测到由于用户代码而导致的错误时,它应该抛出IllegalStateExceptionIllegalArgumentException ,而当库检测到由于库自己的实现而导致的错误时,库应该抛出AssertionError

For example, in the library's tests, you may expect the library throws an IllegalStateException when the order of method calls are wrong. 例如,在库的测试中,当方法调用的顺序错误时,您可能会期望库抛出IllegalStateException But you will never expect the library throws an AssertionError . 但是你永远不会指望库会抛出AssertionError

There is no 'discrepancy' here. 这里没有“差异”。 There is nothing in Bloch's wording that excludes what it says in the JLS. 布洛赫的措辞中没有任何内容排除它在JLS中所说的内容。 Bloch is simply saying that if you have circumstance A, throw this exception. 布洛赫简单地说,如果你有环境A,抛出这个例外。 He is not saying that this exception is/should be thrown only in this condition. 并不是只有在这种情况下才会抛出这个异常。 The JLS is saying this exception is thrown if A, B, or C. JLS说如果A,B或C抛出此异常。

I ran into this with: 我碰到了这个:

try {
    MessageDigest digest = MessageDigest.getInstance("SHA-1");
    ...
} catch (NoSuchAlgorithmException e) {
    throw new AssertionError(e);
}

I think it will be impractical for me to throw IllegalStateException here in place of AssertionException even though this falls into the "the Java environment" category. 我认为在这里抛出IllegalStateException代替AssertionException是不切实际的,尽管这属于“Java环境”类别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM