В java усиленном для цикла, можно ли предположить, что выражение, которое будет зациклировано, будет оцениваться только один раз?
В следующем:
for (String deviceNetwork : deviceOrganizer.getNetworkTypes(deviceManufacturer)) {
// do something
}
Можно ли предположить, что deviceOrganizer.getNetworkTypes(deviceManufacturer) будет вызываться только один раз?
Ответы
Ответ 1
Да, абсолютно.
Из раздел 14.14.2 спецификации:
Если тип выражения является подтипом Iterable, тогда пусть я являюсь типом выражение Expression.iterator(). Расширение для утверждения эквивалентно базовому для формулировка формы:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
VariableModifiersopt Type Identifier = #i.next();
Statement
}
(Альтернатива относится к массивам.)
Обратите внимание, что Expression
упоминается только в первой части выражения цикла цикла - поэтому он оценивается только один раз.
Ответ 2
Да, попробуйте:
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
Ответ 3
В дополнение к сказанному и проверке того, что spec делает то, что он говорит, давайте посмотрим на сгенерированный байт-код для следующего класса, который реализует старые и новые циклы стилей, чтобы перебрать список, возвращенный вызовом метода, getList()
:
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) идентичны.
Сгенерированный байт-код точно такой же.