IllegalStateException 与 UnsupportedOperationException

IllegalStateException vs UnsupportedOperationException

我对使用异常感到困惑:IllegalStateExceptionUnsupportedOperationException.

我有一个在某些情况下不允许使用的删除方法:比方说当调用者拥有有效数据时。

那么我应该给用户一个异常信息,告诉他他现在正在做一个无效的操作。

那么,我应该抛出哪个异常? IllegalStateExceptionUnsupportedOperationException.

我知道我可以使用它们中的任何一个给出详细信息,但我仍然想知道哪个对我来说更好。

来自 Java文档:

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

抛出表示不支持请求的操作。

UnsupportedOperationException应该使用,因为该方法完全不支持,而应该使用IllegalStateException,因为该方法受支持,但在当前国家,这是不合法的。

Iterator class 是说明这两个异常之间区别的很好的候选者。

Iterator 通过抛出 UnsupportedOperationException :

在默认方法中实现 remove()
public interface Iterator<E> {
    ...
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
    ...
}

不覆盖此方法来支持它的实现确实不支持该方法。

关于实现,我们可以看到 ArrayList class 使用的 Iterator 实现覆盖了 remove() 以支持它。所以 UnsupportedOperationException 不再抛出。

另一方面,我们还可以看到,如果您在从未调用 next() 的情况下调用该方法,该方法将抛出 IllegalStateException 以使迭代器前进到下一个元素:

private class Itr implements Iterator<E> {
    ...
    public void remove() {      
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    ...
    }
}

此实现非常支持此方法,但如果您在非法状态下调用它,则会抛出 IllegalStateException

IllegalStateException: 这个不太常见,但它很有用,因为它依赖于已调用的先前方法。

例如,如果您的对象需要在其他方法之前调用它的 initialise() 方法,那么您可以在 initialise() 中设置一个标志,如果没有调用 initialise() 则抛出 IllegalStateException:

private boolean initted;

public void initialise() {
  // ...
  initted = true;
}
public void doSomething() {
  if (!initted)
    throw new IllegalStateException("Object not initialised");
}

UnsupportedOperationException: 此异常是为您覆盖抽象 class 或实现接口但不想或不能实现某些方法的情况而设计的。

它被 Java 集合框架的各种 class 所使用。理想情况下,您的接口或方法还应该为调用者提供一种方法,以预先确定它是否希望支持给定的操作。