Точно ли определен порядок итерации Java foreach для примитивов?
Вопрос
Пример кода:
int a[] = new int[]{0, 1, 2, 3};
int result = 0;
for (int i : a)
result += i;
Гарантируется ли повторение цикла через a[0]
, a[1]
, a[2]
, a[3]
в таком порядке?Я твердо верю, что ответ - да, но эта страница похоже, не совсем однозначно излагается порядок.
Есть надежная рекомендация?
Решение
Согласно JLS, усовершенствованный for
заявление, ваш цикл for эквивалентен
int[] array = a;
for (int index = 0; index < a.length; index++) {
int i = array[index];
result += i;
}
"где array
и index
являются сгенерированными компилятором идентификаторами, отличными от любых других идентификаторов (сгенерированных компилятором или иным образом), которые находятся в области видимости в точке, где расширенное for
происходит утверждение ". (слегка перефразируя здесь имена переменных).
Так что да:заказ абсолютно гарантирован.
Другие советы
Видишь раздел 14.14.2 спецификации языка Java, 3-е издание.
Если тип выражения является подтипом Iterable , то пусть I будет типом выражения Expression.iterator().Расширенный оператор for эквивалентен базовому оператору for, имеющему вид:
for (I #i = Expression.iterator(); #i.hasNext(); ) { VariableModifiersopt Type Identifier = #i.next(); Statement }
Где #i - сгенерированный компилятором идентификатор, который отличается от любых других идентификаторов (сгенерированных компилятором или иным образом), которые находятся в области видимости (§6.3) в точке, где встречается оператор enhanced for .
В нем говорится , что в JLS это:
for ( VariableModifiersopt Type Identifier: Expression) Statement
эквивалентно
T[] a = Expression;
L1: L2: ... Lm:
for (int i = 0; i < a.length; i++) {
VariableModifiersopt Type Identifier = a[i];
Statement
}
Я не нашел на странице, на которую вы ссылались, ничего, что подразумевало бы неупорядоченную итерацию.Можете ли вы опубликовать конкретную цитату?
В любом случае, я нахожу, что этот код:
public static void main( String args[] ) {
double a[] = new double[] { 0, 1, 2, 3 };
int result = 0;
for ( double i : a ) {
result += i;
}
декомпилирует до зацикливания в старом стиле:
public static void main(String args[])
{
double a[] = {
0.0D, 1.0D, 2D, 3D
};
int result = 0;
double ad[];
int k = (ad = a).length;
for(int j = 0; j < k; j++)
{
double i = ad[j];
result = (int)((double)result + i);
}
}
Конечно, это не то же самое, что гарантия, но, по крайней мере, неупорядоченная итерация по массиву была бы очень странной и, казалось бы, противоречила бы очевидной реализации здравого смысла.