[英]In a java enhanced for loop, is it safe to assume the expression to be looped over will be evaluated only once?
In the following: 在下面的:
for (String deviceNetwork : deviceOrganizer.getNetworkTypes(deviceManufacturer)) {
// do something
}
Is it safe to assume that deviceOrganizer.getNetworkTypes(deviceManufacturer) will be called only once? 假设deviceOrganizer.getNetworkTypes(deviceManufacturer)只被调用一次是否安全?
Yes, absolutely. 是的,一点没错。
From section 14.14.2 of the spec : 从规范的第14.14.2节 :
If the type of Expression is a subtype of Iterable, then let I be the type of the expression Expression.iterator().
如果Expression的类型是Iterable的子类型,那么让我成为表达式Expression.iterator()的类型。 The enhanced for statement is equivalent to a basic for statement of the form:
增强的for语句相当于表单的基本for语句:
for (I #i = Expression.iterator(); #i.hasNext(); ) { VariableModifiersopt Type Identifier = #i.next(); Statement }
(The alternative deals with arrays.) (替代方案涉及数组。)
Note how Expression
is only mentioned in the first part of the for loop expression - so it's only evaluated once. 注意
Expression
是如何仅在for循环表达式的第一部分中提到的 - 所以它只被评估一次。
Yes, give it a try: 是的,试一试:
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};
}
}
Output: 输出:
$ java ForLoop
Test data invoked
1
2
3
4
To complement what's been said and verify that the spec is doing what it says, let's look at the generated bytecode for the following class, which implements the old and new style loops to loop over a list returned by a method call, getList()
: 为了补充已经说过的内容并验证规范是否正在执行它所说的内容,让我们看一下下面类生成的字节码,它实现了旧的和新的样式循环来循环遍历方法调用返回的列表
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);
}
}
}
Relevant parts of the output: 输出的相关部分:
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
This shows that the first loop (0 to 32) and the second (35-67) are identical . 这表明第一个循环(0到32)和第二个循环(35-67)是相同的 。
The generated bytecode is exactly the same . 生成的字节码完全相同 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.