2010-12-30 5 views
7
String[] strs = new String[] { "1", "2", ... , "6" }; 

for (String s : strs) { 
    System.out.println(s); 
} 

Questa è una domanda su java internals.Come fa a Java l'iterazione di una matrice

Nell'esempio di codice precedente, in che modo il ciclo foreach determina la lunghezza dell'array? Gli array sono effettivamente oggetti internamente o utilizzano roba come sizeof inaccessibile ai programmatori front-end?

Ho la sensazione che mi manchi solo qualcosa di stupido, ma immagino che potrebbe anche essere bello. :-)

+0

possibile duplicato di [Come funziona Java per ciascun ciclo?] (Http://stackoverflow.com/questions/85190/how-does-the-java-for-each-loop-work) –

+1

+1 interessante domanda, e per niente un duplicato. –

+0

Non proprio. So già che è iterabile, ma come fa l'iteratore a sapere quando interrompere l'iterazione? – SapphireSun

risposta

11

ho compilato il seguente codice:

public class ArrayIterator 
{ 
    public static void main(String[] argv) 
    { 
     String[] strs = new String[] { "1", "2", "3", "4", "5" }; 
     enhancedPrint(strs); 
     normalPrint(strs); 
    } 

    public static void enhancedPrint(String[] strs) 
    { 
     for (String s : strs) 
     { 
      System.out.println(s); 
     } 
    } 

    public static void normalPrint(String[] strs) 
    { 
     String[] localArray = strs; 
     int len = localArray.length; 
     for (int i = 0; i < len; i++) 
     { 
      String s = localArray[i]; 
      System.out.println(s); 
     } 
    } 
} 

Questa è la smontato (javap -c ArrayIterator) bytecode per le funzioni di iterazione:

la stampa migliorata:

public static void enhancedPrint(java.lang.String[]); 
    Code: 
    0: aload_0 
    1: astore_1 
    2: aload_1 
    3: arraylength 
    4: istore_2 
    5: iconst_0 
    6: istore_3 
    7: iload_3 
    8: iload_2 
    9: if_icmpge 31 
    12: aload_1 
    13: iload_3 
    14: aaload 
    15: astore 4 
    17: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream; 
    20: aload 4 
    22: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    25: iinc 3, 1 
    28: goto 7 
    31: return 

Un normale ciclo for:

public static void normalPrint(java.lang.String[]); 
    Code: 
    0: aload_0 
    1: astore_1 
    2: aload_1 
    3: arraylength 
    4: istore_2 
    5: iconst_0 
    6: istore_3 
    7: iload_3 
    8: iload_2 
    9: if_icmpge 31 
    12: aload_1 
    13: iload_3 
    14: aaload 
    15: astore 4 
    17: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream; 
    20: aload 4 
    22: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    25: iinc 3, 1 
    28: goto 7 
    31: return 

Come si può vedere, in entrambi i casi, il compilatore sta caricando la lunghezza array (strs.length) e loop contro di esso. Vediamo che il ciclo for-enhanced per ogni array, nel caso di una matrice, è zucchero sintattico per il looping sulla lunghezza dell'array (piuttosto che nel caso di un oggetto in cui usa un Iterator).


Ho modificato il 'normale' ciclo f tale che è molto meno idiomatica, ma che ha lo stesso bytecode come avanzato per ciclo. A tutti gli effetti, la versione normale for loop è ciò che il compilatore genera quando compila l'enhanced per ogni ciclo.

+0

Whoa! Molte grazie! – SapphireSun

3

Sì, c'è qualcosa di simile a l'operatore C++ sizeof - è la variabile length istanza Il campo length (che dà il numero di elementi nella matrice, non la dimensione in byte.) è sempre un membro pubblico dell'array, quindi è accessibile ai programmatori Java.

E sì, gli array sono objects e non solo internamente.

(Più in generale, la sintassi for circuito funziona come descritto nella question che org.life.java legata a, ma che non è proprio quello che stavi chiedendo.)

Problemi correlati