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

В следующем:

for (String deviceNetwork : deviceOrganizer.getNetworkTypes(deviceManufacturer)) {
    // do something
}

Можно ли предположить, что deviceOrganizer.getNetworkTypes (deviceManufacturer) будет вызываться только один раз?

Ответы [ 3 ]

18 голосов
/ 22 апреля 2010

Да, абсолютно.

Из раздела 14.14.2 спецификации :

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

for (I #i = Expression.iterator(); #i.hasNext(); ) {
        VariableModifiersopt Type Identifier = #i.next();
   Statement
}

(альтернатива относится к массивам.)

Обратите внимание, что Expression упоминается толькопервая часть выражения цикла for, поэтому оно вычисляется только один раз.

7 голосов
/ 22 апреля 2010

Да, попробуйте:

public class ForLoop {
    public static void main( String [] args ) {
        for( int i : testData() ){
            System.out.println(i);
        }
    }
    public  static int[] testData() {
        System.out.println("Test data invoked");
        return new int[]{1,2,3,4};
    }
}

Выход:

$ java ForLoop
Test data invoked
1
2 
3
4
1 голос
/ 22 апреля 2010

Чтобы дополнить сказанное и убедиться, что спецификация выполняет то, что говорит, давайте посмотрим на сгенерированный байт-код для следующего класса, который реализует циклы старого и нового стилей для циклического перебора списка, возвращаемого вызовом метода 1001 * * * 1002

public class Main {
    static java.util.List getList() { return new java.util.ArrayList(); }
    public static void main(String[] args) {
        for (Object o : getList()) {
            System.out.print(o);
        }
        for (java.util.Iterator itr = getList().iterator(); itr.hasNext(); ) {
            Object o = itr.next(); System.out.print(o);
        }
    }
}

Соответствующие части продукции:

   0:   invokestatic    #4; //Method getList
   3:   invokeinterface #5,  1; //InterfaceMethod java/util/List.iterator
   8:   astore_1
   9:   aload_1
   10:  invokeinterface #6,  1; //InterfaceMethod java/util/Iterator.hasNext
   15:  ifeq    35
   18:  aload_1
   19:  invokeinterface #7,  1; //InterfaceMethod java/util/Iterator.next
   24:  astore_2
   25:  getstatic   #8; //Field java/lang/System.out
   28:  aload_2
   29:  invokevirtual   #9; //Method java/io/PrintStream.print
   32:  goto    9
   35:  invokestatic    #4; //Method getList
   38:  invokeinterface #10,  1; //InterfaceMethod java/util/List.iterator
   43:  astore_1
   44:  aload_1
   45:  invokeinterface #6,  1; //InterfaceMethod java/util/Iterator.hasNext
   50:  ifeq    70
   53:  aload_1
   54:  invokeinterface #7,  1; //InterfaceMethod java/util/Iterator.next
   59:  astore_2
   60:  getstatic   #8; //Field java/lang/System.out
   63:  aload_2
   64:  invokevirtual   #9; //Method java/io/PrintStream.print
   67:  goto    44
   70:  return

Это показывает, что первый цикл (от 0 до 32) и второй (35-67) идентичны .
Сгенерированный байт-код точно такой же .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...