在pop
的{{1}}方法中,如果堆栈为空,它将抛出java.util.Stack
。但是EmptyStackException
的{{1}}方法(类似于remove
类中的java.util.Queue
)抛出pop
。为什么Java中会有这种不一致的地方?
答案 0 :(得分:35)
OutOfMemoryException:Java heap space
类是引入集合框架之前的Java 1.0以来的遗留类。它的界面必须向后兼容……这就是它的设计方式。
相比之下,Stack
接口是在collections框架的Java 1.5修订版中引入的。到那时,Queue
已被设计人员选择为表达这种错误条件的最佳方法 1 。
请注意,{em}可以在NoSuchElementException
中使用NoSuchElementException
,因为两个类都存在于Java 1.0中,但是显然,设计者还有其他想法然后 2 。
因此,这只是Java API的发展方式引起的历史异常。如果不破坏使用Stack
类的现有应用程序的二进制兼容性,就不能解决该问题。
1-您可能不同意,但是您问为什么,这就是为什么。
2-也许他们只是太着急而无法正确地设计API。 Java 1.0发行版在承受巨大市场压力的巨大压力下进行了开发。犯了一些错误,无法及时纠正。其他示例包括Stack
API,不推荐使用的Enumeration
方法,Thread
和Hashtable
类,Vector
等。但是,一旦Java 1.1发布,就为时已晚。
答案 1 :(得分:9)
首先是Stack类。在Javadoc中,它表示“自JDK 1起”。它定义了自己的异常类型,因为……可以。
同时,NoSuchElementException已经存在,但是Java集合框架还不存在。因此,广泛使用该例外还不太普遍。这是“只是预定义的例外之一”类型。
在Java 1.2中添加了collections框架,它不能使用StackEmptyException
,因为它的名称限制了它只能与堆栈一起使用。
那时,不能再修改旧的Stack类,因为那样会破坏现有代码。 Java在向后兼容方面已经取得了成功,数十年来,异常不一致是这种兼容性的一个标志。
要获得正式答复,您可以look at the code。它说:
@author乔纳森·佩恩(Jonathan Payne)
如果真的很重要,您可以直接与他联系并询问他是否记得他20年前的所作所为。也许他会。 :)
答案 2 :(得分:6)
Queue
具有e.__cause__.diag
,这使它可以返回null
代替引发异常。在special methods的情况下这很有用,BlockingQueue
应该阻塞直到出现值或引发异常。
在这种情况下,旧类-Stack
-的特殊之处在于,它为空时会抛出自己的异常。这里没有真正的矛盾,因为例外是不同的,只是集合服务于两个完全不同的目的。如果没有其他说明,则可以通过例外有所不同的事实来明确记录。
答案 3 :(得分:3)
我想您对此没有任何不一致或任何困惑。方法pop()和remove()都是不言自明的,并且扩展了RuntimeException。这些例外按照适当的约定命名,并自行解释。
队列-> remove()
抛出NoSuchElementException。根据文档,remove()
检索并删除此队列的头。因此,如果函数仅执行检索,则它可以返回null且不引发Exception(Refer,poll()
)。除了检索之外,它还会尝试删除队列的头部,因此会引发NoSuchElementException。
Stack-> pop()
抛出EmptyStackException,这意味着堆栈为空(逻辑上它也可以抛出NoSuchElementException,但是EmptyStackException更干净且易于调试原因。而且,仅由堆栈类)
确切的答案是Stack是一个类,而Queue是一个接口。 您可以构造自己的Stack类对象,这意味着它可以恰好具有Exceptions。
但是Queue作为接口,实际的方法声明依赖于(例如,LinkedList
)。因此,如果您打算自己实现Queue<E>
,则可以拥有EmptyQueueException
或任何您喜欢的东西。但是,如果您依赖LinkedList
,那么从EmptyQueueException
LinkedList.remove()
根本不合逻辑