2010-04-21 9 views
13

:Bir döngü için geliştirilmiş bir java'da, döngülenecek ifadenin yalnızca bir kez değerlendirileceğini varsaymak güvenli midir? Aşağıdaki yılında

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

o deviceOrganizer.getNetworkTypes (deviceManufacturer) yalnızca bir kez adı verilecek varsaymak güvenli mi?

+3

İçtenlikle umuyoruz, yeniden yazmak için çok fazla kodum var ... – skaffman

+0

http://stackoverflow.com/questions/1618202/java-foreach-loop –

+3

@Pascal Thivent - kullanıcısının olası kopyası ama benim başlığım daha iyi :) – morgancodes

cevap

18

Evet, kesinlikle. section 14.14.2 of the spec itibaren

: İfade tipi iterable bir alt tipi ise

, o zaman ben ifadesi Expression.iterator() tipi olsun. deyimi için geliştirilmiş formun deyimi için temel bir eşdeğerdir: (. dizilerle alternatif fırsatlar)

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

Expression sadece ilk bölümü için belirtilen nasıl Not döngü ifadesi - bu yüzden sadece bir kez değerlendirilir.

7

Evet, bir deneyin:

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}; 
    } 
} 

Çıktı:

$ java ForLoop 
Test data invoked 
1 
2 
3 
4 
1

söylenir şeyi tamamlayacak ve spec ne diyor yaptığını doğrulamak için en için oluşturulan bayt bakalım 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 Eski ve yeni stil döngülerinin bir yöntem çağrısı tarafından döndürülen bir listenin üzerinden geçmesini sağlayan aşağıdaki sınıf. çıkış

ilgili parça:

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 

bu ilk halka (32 0) ve ikinci (35-67) özdeş olduğunu göstermektedir.
Oluşturulan bayt kodu, tam olarak ile aynıdır.

+2

Oh adam ... biz ** bayt kodlarına bakmak zorunda mıyız? JLS'nin belirttiği şeyle devam edemez miyiz? –

+0

LOL Teşekkürler stephen, tam olarak ne düşündüğümü. OP'ye basmamak için ama benim görüşüme göre bytecode bu durumda ona yardımcı olamaz –

İlgili konular