Почему я не могу использовать foreach на перечислении Java?
почему я не могу сделать:
Enumeration e = ...
for (Object o : e)
...
6 ответов:
, потому что
Enumeration<T>
не распространяетсяIterable<T>
. Вот это пример создания итерационных перечислений.почему это интересный вопрос. Это не совсем ваш вопрос, но он проливает некоторый свет на это. Из JAVA Collections API Design FAQ:
почему итератор не расширяет перечисление?
мы просматриваем имена методов для Перечисление как несчастный. Они очень долго, и очень часто используется. Учитывая, что мы добавляли метод и создавая совершенно новую структуру, мы считает, что было бы глупо не воспользуйтесь возможностью улучшите имена. Конечно, мы могли бы поддержите новые и старые имена внутри Итератор, но это не кажется стоящий.
это в основном говорит мне о том, что Sun хочет дистанцироваться от перечисления, что очень рано Java с довольно многословным синтаксис.
используя служебный класс Collections, перечисление можно сделать итерационным, например:
Enumeration headerValues=request.getHeaders("mycustomheader"); List headerValuesList=Collections.list(headerValues); for(Object headerValueObj:headerValuesList){ ... do whatever you want to do with headerValueObj }
я решил эту проблему с двумя очень простыми классами, один для
Enumeration
иIterator
. Оболочка перечисления выглядит следующим образом:static class IterableEnumeration<T> extends Object implements Iterable<T>, Iterator<T> { private final Enumeration<T> enumeration; private boolean used=false; IterableEnumeration(final Enumeration<T> enm) { enumeration=enm; } public Iterator<T> iterator() { if(used) { throw new IllegalStateException("Cannot use iterator from asIterable wrapper more than once"); } used=true; return this; } public boolean hasNext() { return enumeration.hasMoreElements(); } public T next() { return enumeration.nextElement(); } public void remove() { throw new UnsupportedOperationException("Cannot remove elements from AsIterator wrapper around Enumeration"); } }
который может быть использован либо со статическим методом утилиты (который является моим предпочтением):
/** * Convert an `Enumeration<T>` to an `Iterable<T>` for a once-off use in an enhanced for loop. */ static public <T> Iterable<T> asIterable(final Enumeration<T> enm) { return new IterableEnumeration<T>(enm); } ... for(String val: Util.asIterable(enm)) { ... }
или путем создания экземпляра класса:
for(String val: new IterableEnumeration<String>(enm)) { ... }
новый стиль для цикла ("foreach") работает с массивами и вещами, которые реализуют
Iterable
интерфейс.это также более аналогично
Iterator
чемIterable
, Так что это не имеет смысла дляEnumeration
работать с foreach еслиIterator
тоже (и это не).Enumeration
также не рекомендуется в пользуIterator
.
Enumeration
не выполнятьIterable
и как таковой не может быть использован непосредственно в цикле foreach. Однако с помощью Apache Commons Collections можно перебирать перечисление с помощью:for (Object o : new IteratorIterable(new EnumerationIterator(e))) { ... }
вы также можете использовать сокращенный синтаксис с
Collections.list()
но это менее эффективно (две итерации по элементам и больше памяти) :for (Object o : Collections.list(e))) { ... }