为什么Java没有EmptyQueueException?

26

java.util.Stackpop 方法会在栈为空时抛出 EmptyStackException 异常。然而,java.util.Queueremove 方法(类似于 Stack 类中的 pop)却会抛出 NoSuchElementException 异常。为什么 Java 中存在这种不一致性?

4个回答

37

Stack类是Java 1.0时代的一个遗留类,在集合框架引入之前就存在了。它的接口必须向后兼容...这也是它设计的初衷。

相比之下,Queue接口是在Java 1.5版本的集合框架中引入的。到那个时候,NoSuchElementException被设计者选为表达这种错误条件的最佳方式1

请注意,NoSuchElementException本来可以在Stack中使用,因为在Java 1.0中两个类都存在,但显然,设计者当时有其他想法2

因此,这只是由于Java API的演变方式而产生的历史上的异常情况。它无法修复,因为这样做会破坏使用Stack类的现有应用程序的二进制兼容性。


1 - 您可能不同意这一点,但您问为什么,这就是原因。

2- 或许他们只是太匆忙了,无法正确设计API。Java 1.0版发布时承受着极大的压力以满足市场需求。一些错误是不可避免的并且无法及时纠正。其他例子包括Enumeration API、不赞成使用的Thread方法、HashtableVector类、StringBuffer等等。但是一旦Java 1.1发布了,就为时已晚。


10

Stack类是最早存在的。在Javadoc中它说“自JDK 1以来”(since JDK 1)。它定义了自己的异常类型,因为它可以。

同时,NoSuchElementException已经存在,但Java集合框架还不存在。因此,广泛使用该异常还不太普遍。它只是“预定义异常”类型之一。

集合框架被添加到Java 1.2中,由于名称限制,它不能使用StackEmptyException,这将使其仅限于与栈一起使用。

这时,旧的Stack类不能再修改,否则会破坏现有代码。Java多年来一直成功地保持向后兼容性,异常不一致是这种兼容性的一种体现。


要获得官方答案,您可以查看代码。它说:

 

@作者Jonathan Payne

如果你真的很重要,你可以直接联系他,问他是否还记得20年前他做了什么。也许他记得。:)


3
没错,但是 Stack 的父类 Vector 在 1.0 版本中就已经存在并使用了 NoSuchElementException。Enumeration(以及它的子类)也是如此。因此,已经有多个(尽管不属于集合框架)类在使用 NoSuchElementException。 - Vasan

6
Queue具有特殊方法,可以返回null而不是抛出异常。在BlockingQueue的情况下非常有用,它应该阻塞直到出现值,或者抛出异常。

在这种情况下,传统类 - Stack - 是特殊的,因为当它为空时会抛出自己的异常。这里没有真正的不一致之处,只是集合正在服务于两个完全不同的目的。如果没有其他问题,这明确地通过异常不同来记录。


你是指 poll 方法吗? - Hai Hoang
4
值得注意的是,许多其他的集合类和类似集合的类也使用NoSuchElementException来表示它们为空 - 从Enumeration到Stack自己的超类Vector,应有尽有。 - Vasan
@HaiHoang: offerpollpeek - Makoto

3
我想你对此没有任何不一致或混淆。pop()和remove()这两种方法都是不言自明的,并且扩展了RuntimeException。异常的命名符合规范,本身就代表了解释。
队列-> remove()会抛出NoSuchElementException。根据文档,remove()检索并删除此队列的头部。因此,如果该函数仅执行检索,则可以返回null而不是抛出异常(参见poll())。除了检索之外,它还试图删除队列的头部,因此会抛出NoSuchElementException。
栈-> pop()抛出EmptyStackException,这意味着栈为空(从逻辑上讲,它也可以抛出NoSuchElementException,但EmptyStackException更加清晰易于调试原因。此外,只有Stack类会抛出此异常)。
谈到你的确切答案,Stack是一个类,而Queue是一个接口。您可以构建自己的Stack类对象,这意味着它可以精确地具有异常。
但是,Queue作为一个接口,依赖于(例如LinkedList)的实际方法声明。因此,如果您计划自己实现Queue ,则可以拥有EmptyQueueException或任何您喜欢的内容。但是,如果您依赖于LinkedList,则不合逻辑地期望从LinkedList.remove()中获得EmptyQueueException。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接