IllegalStateException的用途是什么?

这与今天的同事讨论。

Java的IllegalStateException的Javadocs声明:

表示某个方法在非法或不适当的时间被调用。 换句话说,对于请求的操作,Java环境或Java应用程序不处于适当的状态。

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

另一个常见的重用exception是IllegalStateException。 如果由于接收对象的状态而导致调用是非法的,则这通常是抛出的exception。 例如,如果调用者在正确初始化之前尝试使用某个对象,这将是一个例外。

这里似乎有点不一致。 javadocs的第二个句子使得听起来像exception可以描述关于Java执行状态的一个非常广泛的条件,但Effective Java中的描述听起来像是用于特定于与其对象的状态状态相关的条件方法已被调用。

我在JDK中看到的使用方法(例如collections, Matcher )和Guava,似乎都属于Effective Java谈论的范畴(“这个对象处于无法调用这个方法的状态)”。 这也与IllegalStateException的兄弟IllegalArgumentException一致。

JDK中是否存在与“Java环境”或“Java应用程序”相关的合法IllegalStateExceptionexception? 或者是否有任何最佳实践指南提倡将其用于更广泛的执行状态? 如果不是的话,为什么哈维是这样expression的? ;)

这是JDK中这个exception的一个特别合法的用法(参见: URLConnection.setIfModifiedSince(long)在其他300多种用法中:

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

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

这个exception特别有用,当你的类有一些状态(状态机?),随着时间的推移而变化,使一些方法不相关或不可能。 想想有一个Car类有start()stop()fuel()方法。 虽然两次,一个接一个地调用start()可能没有错,但是为一辆起步的汽车加油肯定是一个坏主意。 即 – 汽车处于错误的状态。

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

这里是JDK中的一个例子。 有一个名为java.lang.Shutdown的包私有类。 如果系统正在closures,并且您尝试添加新的挂钩,则会引发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”指南和“Effective Java”指南之间没有区别。 由于执行关机的方式,JVM的closures存储在一个称为状态的字段中。 因此,它也符合何时使用IllegalStateException的“Effective Java”指导,因为“state”字段是接收对象状态的一部分。 由于接收对象(Shutdown)处于错误状态,因此会引发IllegalStateException。

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

我猜如果你看到IllegalStateException用法,我会说如果更合适的话。 这个exception用在很多包中

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

指定一个示例如果队列已满, ArrayBlockingQueue.add将引发此exception。 现在满了状态的对象,它被调用在不适当的或非法的时间

我猜两者的意思是相同的,但措辞的差异。

这里没有“差异”。 布洛赫的措辞中没有什么不包括它在JLS中所说的。 布洛赫只是说,如果你有情况A,抛出这个exception。 他并不是只有在这种情况下才会抛出这个例外。 JLS说如果A,B或C引发这个exception

我碰到这个:

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

我认为在这里抛出IllegalStateException ,而不是AssertionException这是不切实际的,尽pipe这属于“Java环境”范畴。

给定一个库,只要它检测到由于用户代码造成的错误,就应该抛出一个IllegalStateExceptionIllegalArgumentException ,而当库检测到一个由于库本身的实现而导致的错误时,它应该抛出一个AssertionError

例如,在库的testing中,当方法调用顺序错误时,您可能会期望该库抛出IllegalStateExceptionexception。 但是你永远不会期望这个库会抛出一个AssertionError