В соответствии с Спецификацией языка Java, § 14.14.2, переменная расширенного цикла for
должна быть локальной в цикле. Другими словами, это компилируется:
for (State state : State.values()) {
// do something for each state
}
но это не так:
State state;
for (state: State.values()) {
// do something for each state
}
JLS не дает оснований для выбора этого языка. Я могу понять, почему имя типа должно присутствовать, если локальная переменная изменена на final
или аннотацией, но я не понимаю, почему запрещенное имя переменной, объявленной в другом месте, недопустимо. Кто-нибудь знает, почему это ограничение было наложено?
ИЗМЕНИТЬ
Несколько ответов до сих пор, похоже, указывают на то, что то, что происходит вне цикла, является основанием для разработки языка таким образом. Возможно, более пристальное изучение того, что говорит JLS, прояснит, почему я не считаю это убедительным. Рассмотрим этот цикл, где State
- перечисление:
for (State state : State.values()) {
// ...
}
State.values()
- это массив, поэтому, согласно JLS, цикл функционально идентичен:
State[] a = State.values();
for (int i = 0; i < a.length; i++) {
State state = a[i];
// ...
}
Теперь ясно, что этот последний цикл мог быть написан:
State state;
State[] a = State.values();
for (int i = 0; i < a.length; i++) {
state = a[i];
// ...
}
Концептуально этот последний (совершенно законный) цикл мог бы использоваться как функциональный эквивалент второго расширенного цикла for
выше (тот, который не компилируется).
Аналогично, если stateList
является Iterable<State>
(а не массивом), этот цикл:
for (State state : stateList) {
// ...
}
функционально идентичен:
for (Iterator<State> iterator = stateList.iterator(); iterator.hasNext(); ) {
State state = iterator.next();
// ...
}
Как и раньше, этот последний цикл можно было бы написать:
State state;
for (Iterator<State> iterator = stateList.iterator(); iterator.hasNext(); ) {
state = iterator.next();
// ...
}
Опять же, это могло быть использовано как функциональный эквивалент (незаконный):
State state;
for (state : stateList) {
// ...
}
В каждом случае, когда цикл выходит, значение State
отлично определено (если, возможно, бесполезно). Кроме того, как и в регулярном цикле, расширенный цикл for
с использованием неизвестного неизвестного имени переменной (например, строка State state;
отсутствует или выходит за рамки) может быть обнаружена во время компиляции. Итак, с точки зрения дизайна языка, какая проблема? Почему разработчики языка вне закона эту конструкцию?