What's the intended use of IllegalStateException?

Solution 1:

Here is one particularly legitimate usage of this exception in JDK (see: URLConnection.setIfModifiedSince(long) among 300+ other usages of it:

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. While calling start() twice, one after another, is probably nothing wrong, but fueling a started car is certainly a bad idea. 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. 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.

Solution 2:

Here is an example in the JDK. There is a package private class called java.lang.Shutdown. If the system is shutting down and you attempt to add a new hook, it throws the 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.

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. Because of the way Shutdown is implemented, the shutdown-ness of the JVM is stored in a field called 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. Since the receiving object (Shutdown) is in the wrong state, it throws the IllegalStateException.

In my opinion the two descriptions of when to use IllegalStateException are consistent. The Effective Java description is a bit more practical, that's all. 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.