簡體   English   中英

在java增強的for循環中,可以安全地假設要循環的表達式只會被評估一次嗎?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM