В java, улучшенном для цикла, безопасно ли предполагать, что зацикленное выражение будет оцениваться только один раз? - PullRequest
10 голосов
/ 24 октября 2009

В Java цикл для каждого.
Если у меня есть метод, который генерирует массив, называется genArray().

В следующем коде будет ли массив каждый раз перегенерироваться путем вызова genArray()? Или Java однажды вызовет метод и сохранит копию из массива?

for (String s : genArray())
{
    //...
}

Спасибо

Ответы [ 3 ]

23 голосов
/ 24 октября 2009

О расширенный для оператора , спецификации языка Java пишет:

Усовершенствованный оператор for имеет форма:

EnhancedForStatement:
        for ( VariableModifiersopt Type Identifier: Expression) Statement

Выражение должно иметь тип Iterable или это должно быть тип массива (§10.1) или время компиляции возникает ошибка.

Область локальной переменной объявлена в части FormalParameter расширенный оператор for (§14.14) Содержимое заявление

Значение расширенного for заявление дается переводом на базовое for утверждение.

Если тип Expression является подтип Iterable, тогда пусть I будет тип выражения Expression. iterator(). Расширенный оператор for эквивалентен к основному for утверждению форма:

for (I #i = Expression.iterator(); #i.hasNext(); ) {

        VariableModifiersopt Type Identifier = #i.next();
   Statement
}

Где #i - генерируется компилятором идентификатор, отличный от любого другие идентификаторы (генерируемые компилятором или иным образом), которые находятся в сфере действия (§6.3) в точке, где улучшено для заявление происходит.

В противном случае выражение обязательно имеет тип массива, T[]. Пусть L1 ... Lm быть (возможно, пустой) последовательностью этикетки, непосредственно предшествующие расширенное for заявление. Тогда Значение расширенного для заявления дается следующим основным for утверждение:

T[] a = Expression;
L1: L2: ... Lm:
for (int i = 0; i < a.length; i++) {
        VariableModifiersopt Type Identifier = a[i];
        Statement
}

Где a и i генерируются компилятором идентификаторы, которые отличаются от любых другие идентификаторы (генерируемые компилятором или иным образом), которые находятся в области Точка, где расширен для утверждения происходит.

Итак, в вашем случае genArray() возвращает не подтип Iterable, а тип массива, поэтому ваш расширенный оператор for эквивалентен следующему базовому for утверждению:

String[] a = genArray();
...
for (int i = 0; i < a.length; i++) {
    String s = a[i];
    // ...
}

И genArray(), таким образом, будет вызываться только один раз (но принятый в настоящее время ответ частично неверен).

5 голосов
/ 24 октября 2009

Он должен привыкнуть только один раз - это то же самое, что вызвать это:

  String[] strings = genArray();
  for (String s : strings) {
  ...
5 голосов
/ 24 октября 2009

Java вызовет genArray () один раз, получит объект итератора и вызовет его несколько раз.

...