О семантике расширенной for
петли
Вот соответствующие выдержки из Спецификации языка Java, 3-е издание , слегка отредактированные для ясности:
Расширенный оператор for
имеет вид:
for ( Type Identifier : Expression ) Statement
Если тип Expression
является типом массива, T[]
, то значение расширенного оператора for
определяется следующим базовым оператором for
:
T[] a = Expression;
for (int i = 0; i < a.length; i++) {
Type Identifier = a[i];
Statement
}
где a
и i
- это идентификаторы, сгенерированные компилятором, которые отличаются от любых других идентификаторов (генерируемых компилятором или иным образом), которые находятся в области действия в точке, где происходит расширенный оператор for
.
Таким образом, фактически язык гарантирует, что Expression
будет оцениваться только один раз.
Для полноты вот эквивалентность, когда Expression
имеет тип Iterable
:
Расширенный оператор for
имеет вид:
for ( Type Identifier : Expression ) Statement
Если тип Expression
является подтипом Iterable
, то пусть I
будет типом выражения Expression.iterator()
. Расширенный оператор for
эквивалентен базовому оператору for
в форме:
for (I iter = Expression.iterator(); iter.hasNext(); ) {
Type Identifier = iter.next();
Statement
}
, где iter
- это идентификатор, сгенерированный компилятором, который отличается от любых других идентификаторов (генерируемых компилятором или иным образом), которые находятся в области действия в точке, где происходит расширенный оператор for
.
Обратите внимание, что это ошибка времени компиляции, если Expression
не является ни Iterable
, ни массивом, поэтому приведенные выше два являются единственными случаями, когда вы можете использовать расширенный цикл for
. Кроме того, для ясности приведенные выше цитаты не содержат информации о любых метках, прикрепленных к циклу for
, и любых модификаторах, прикрепленных к Identifier
, но они обрабатываются так, как и следовало ожидать.
О производительности улучшенной for
петли
Вот цитата из Effective Java 2nd Edition, Item 46: Предпочитайте циклы for-each вместо традиционных циклов for
Цикл for-each, представленный в выпуске 1.5, избавляет от беспорядка и возможности ошибки, полностью скрывая итератор или индексную переменную. Получающаяся идиома в равной степени относится к коллекциям и массивам. Обратите внимание, что при использовании цикла for-each не снижается производительность даже для массивов. Фактически, он может предложить небольшое преимущество в производительности по сравнению с обычным циклом for
в некоторых случаях, так как он вычисляет ограничение индекса массива только один раз. Хотя вы можете делать это вручную, программисты не всегда делают это.
Таким образом, в книге утверждается, что на самом деле некоторые компиляторы выходят за рамки преобразования JLS и выполняют дополнительную оптимизацию для цикла for-each (при этом, конечно, сохраняя его семантику).
Таким образом, вам не нужно беспокоиться о производительности цикла for-each. Спецификация языка разумна (Expression
оценивается только один раз), и именно потому, что это предпочтительная конструкция во многих сценариях , компиляторы позаботятся о том, чтобы оптимизировать их как можно лучше.
Смотри также