Почему 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()