![](/img/trans.png)
[英]In a java enhanced for loop, is it safe to assume the expression to be looped over will be evaluated only once?
[英]In a java enhanced for loop, is it safe to assume the expression to be looped over will be evaluated only once?
在下面的:
for (String deviceNetwork : deviceOrganizer.getNetworkTypes(deviceManufacturer)) {
// do something
}
假設deviceOrganizer.getNetworkTypes(deviceManufacturer)只被調用一次是否安全?
是的,一點沒錯。
從規范的第14.14.2節 :
如果Expression的類型是Iterable的子類型,那么讓我成為表達式Expression.iterator()的類型。 增強的for語句相當於表單的基本for語句:
for (I #i = Expression.iterator(); #i.hasNext(); ) { VariableModifiersopt Type Identifier = #i.next(); Statement }
(替代方案涉及數組。)
注意Expression
是如何僅在for循環表達式的第一部分中提到的 - 所以它只被評估一次。
是的,試一試:
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
為了補充已經說過的內容並驗證規范是否正在執行它所說的內容,讓我們看一下下面類生成的字節碼,它實現了舊的和新的樣式循環來循環遍歷方法調用返回的列表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)是相同的 。
生成的字節碼完全相同 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.