Почему Java не имеет исключения EmptyQueueException?

В pop методе java.util.Stack он выдает EmptyStackException если Stack пуст. Но метод remove java.util.Queue (который похож на pop в классе Stack) вместо этого NoSuchElementException. Почему существует такая несогласованность в Java?

Ответ 1

Класс Stack представляет собой унаследованный класс из Java 1.0 дней, до введения рамки коллекций. Его интерфейс должен быть обратно совместим... и именно так он был разработан.

Напротив, интерфейс Queue был представлен в версии 1.5 для оболочки коллекций. К тому времени разработчики NoSuchElementException как лучший способ выразить такое состояние ошибки 1.

Обратите внимание, что NoSuchElementException можно было использовать в Stack поскольку оба класса существовали в Java 1.0, но, очевидно, у дизайнеров были другие идеи в то время 2.

Таким образом, это просто историческая аномалия, возникшая из-за того, что развились Java API. Он не может быть исправлен без нарушения бинарной совместимости для существующих приложений, которые используют класс Stack.


1 - Вы можете не согласиться с этим, но вы спросили, почему, и именно поэтому.

2 - Или, может быть, они просто слишком спешили, чтобы правильно разработать API.Выпуск Java 1.0 был сделан под сильным давлением, чтобы удовлетворить предполагаемую рыночную возможность.Несколько ошибок были сделаны и не могли быть исправлены вовремя.Другие примеры включают API Enumeration, устаревшие методы Thread, классы Hashtable и Vector, StringBuffer и т.д.Но как только Java 1.1 был выпущен, было уже слишком поздно.

Ответ 2

Класс Stack был первым. В Javadoc говорится: "С JDK 1". Он определил свой собственный тип исключения, потому что... он мог бы.

В то же время NoSuchElementException уже существует, но рамки коллекций Java еще не существовали. Поэтому пока не принято широко использовать это исключение. Это было "только одно из предопределенных исключений".

StackEmptyException коллекций была добавлена в Java 1.2, и она не может использовать StackEmptyException поскольку его имя ограничивает его использование только со стеками.

В этот момент старый класс Stack больше не мог быть изменен, так как это нарушило существующий код. Java успешно добилась обратной совместимости на протяжении десятилетий, и несогласованность исключений является одним из признаков этой совместимости.


Чтобы получить официальный ответ, вы можете посмотреть на код. В нем говорится:

@author Джонатан Пейн

Если вам действительно важно знать, вы можете связаться с ним напрямую и спросить его, помнит ли он, что он делал 20 лет назад. Может, и так. :)

Ответ 3

Queue есть специальные методы, которые позволяют ему возвращать значение null вместо исключения. Это полезно в случае BlockingQueue, который должен блокироваться до появления значения или выдавать исключение.

Унаследованный класс в этом случае - Stack - особенный, поскольку он порождает свое собственное исключение, когда оно пустое. Здесь нет реальной несогласованности в том, что исключения различны, просто, что коллекции служат двум совершенно другим целям. Если ничего другого, это явно задокументировано тем фактом, что исключения отличаются.

Ответ 4

Я думаю, что нет никакого противоречия или какой бы то ни было путаницы, которую вы имеете относительно этого. Оба метода pop() и remove() не требуют пояснений и расширяют RuntimeException. Исключения называются в соответствии с соответствующими соглашениями и для объяснения.

Queue-> remove() выбрасывает исключение NoSuchElementException. Как и в документах, remove() Извлекает и удаляет головку этой очереди. Таким образом, если функция выполняет только поиск, она может вернуть значение null и не выбрасывать исключение (Refer, poll()). В дополнение к поиску, он также пытается удалить головку очереди и, следовательно, вызывается NoSuchElementException.

Stack → pop() выдает EmptyStackException, что означает, что стек пуст (он также может вызывать NoSuchElementException логически, но EmptyStackException более чист и легко отлаживает причину. Кроме того, это исключение выбрано только классом Stack)

Подойдя к вашему точному ответу, Stack - это класс, тогда как Queue - это интерфейс. Вы можете создать свои собственные объекты класса Stack, что означает, что он может иметь исключения именно для него.

Но Queue, являясь интерфейсом, полагается (LinkedList, например) для фактических объявлений метода. Следовательно, если вы планируете реализовать Queue<E> по своему усмотрению, вы можете иметь EmptyQueueException или что угодно. Но если вы полагаетесь на LinkedList, просто EmptyQueueException ожидать EmptyQueueException из LinkedList.remove()