今天与同事讨论了这个问题。
Javadocs for Java的IllegalStateException
声明:
表示在非法或不适当的时间调用了某个方法。换句话说,Java环境或Java应用程序未处于所请求操作的适当状态。
而Effective Java说(第60项,第248页):
另一个常用的异常是IllegalStateException。如果由于接收对象的状态而调用是非法的,则通常会抛出异常。例如,如果调用者在正确初始化之前尝试使用某个对象,则抛出此异常。
这里似乎有一点差异。 javadocs的第二句使得听起来像异常可以描述关于Java执行状态的非常宽泛的条件,但是Effective Java中的描述使得它听起来像是用于特定于与对象的状态状态相关的条件。方法已被调用。
我在JDK中看到的用法(例如集合,Matcher
)和Guava中的用法肯定似乎属于Effective Java谈论的类别(“此对象处于此方法可以处于的状态”被称为“)。这似乎与IllegalStateException
的兄弟IllegalArgumentException
一致。
JDK中是否存在与“Java环境”或“Java应用程序”相关的合法IllegalStateException
用法?或者是否有任何最佳实践指南主张将其用于更广泛的执行状态?如果没有,为什么这样的javadocs就像那样? ;)
答案 0 :(得分:40)
以下是JDK中此异常的一个特别合法的用法(请参阅:URLConnection.setIfModifiedSince(long)
300多个其他用法:
public void setIfModifiedSince(long ifmodifiedsince) {
if (connected)
throw new IllegalStateException("Already connected");
ifModifiedSince = ifmodifiedsince;
}
我认为这个例子很清楚。如果对象处于特定状态(" 已连接"),则不应调用某些操作。在这种情况下,建立连接时,无法设置某些属性。
当您的类具有随时间变化的某些状态(状态机?)时,此异常特别有用,使某些方法无关紧要或不可能。考虑具有Car
,start()
和stop()
方法的fuel()
班级。虽然一次又一次地召唤start()
两次,但可能并没有错,但是为一辆入门的车加油肯定是一个坏主意。即 - 汽车处于错误状态。
可以说好的API不应该允许我们以错误的状态调用方法,以便在编译时发现类似的问题,而不是在运行时。在此特定示例中,连接到URL应返回具有方法子集的不同对象,所有这些方法在连接后都有效。
答案 1 :(得分:4)
以下是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”指南和“Effective Java”指南之间没有区别。由于实现Shutdown的方式,JVM的shutdown-ness存储在一个名为state的字段中。因此,它还满足何时使用IllegalStateException的“Effective Java”指南,因为“state”字段是接收对象状态的一部分。由于接收对象(Shutdown)处于错误状态,因此会抛出IllegalStateException。
在我看来,何时使用IllegalStateException的两个描述是一致的。有效的Java描述更实用,就是这样。对于我们大多数人来说,整个Java环境中最重要的部分是我们现在正在编写的类,因此这是作者关注的内容。
答案 2 :(得分:2)
我想如果你看到IllegalStateException
的用法我会说第二个更合适。此异常用于许多包
如果队列已满,则指定一个示例ArrayBlockingQueue.add会抛出此异常。现在已满是对象的状态,并且在不适当或非法时间调用
我猜两者的含义相同但措辞不同。
答案 3 :(得分:1)
给定一个库,每当它检测到由于用户代码而导致的错误时,它应该抛出IllegalStateException
或IllegalArgumentException
,而当它检测到错误时,库应该抛出AssertionError
到图书馆自己的实施。
例如,在库的测试中,当方法调用的顺序错误时,您可能会期望库抛出IllegalStateException
。但是你永远不会指望图书馆抛出AssertionError
。
答案 4 :(得分:0)
这里没有'差异'。布洛赫的措辞中没有任何内容排除它在JLS中所说的内容。布洛赫简单地说,如果你有环境A,抛出这个例外。他不表示此异常是/应该在这种情况下仅抛出。 JLS表示如果A,B或C,则抛出此异常。
答案 5 :(得分:0)
我遇到了这个:
try {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
...
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
我认为将IllegalStateException
放在AssertionException
以代替{{1}}这对我来说是不切实际的,即使它属于" Java环境"类别。