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

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

Esta es una pregunta acerca de las partes internas de Java.¿Cómo sabe Java cómo iterar una matriz?

En el ejemplo de código anterior, ¿cómo calcula el bucle foreach cuánto tiempo dura la matriz? ¿Las matrices son realmente objetos internos o están usando cosas como sizeof que son inaccesibles para los programadores frontales?

Tengo la sensación de que me estoy perdiendo algo estúpido, pero creo que también podría ser genial. :-)

+0

posible duplicado de [¿Cómo funciona Java para cada ciclo?] (Http://stackoverflow.com/questions/85190/how-does-the-java-for-each-loop-work) –

+1

+1 interesante pregunta, y para nada un duplicado. –

+0

No del todo. Ya sé que es iterable, pero ¿cómo sabe el iterador cuándo detener la iteración? – SapphireSun

Respuesta

11

compilé el siguiente código:

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

Este es el (javap -c ArrayIterator) bytecode desmontado para las funciones de iteración:

la impresión mejorada:

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 bucle normal para:

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 

Como se puede ver, en ambos casos, el compilador está cargando la longitud matrices (strs.length) y el bucle en contra de ella. Vemos que el bucle for-each mejorado, en el caso de una matriz, es azúcar sintáctica para el bucle contra la longitud de la matriz (en lugar de en el caso de un objeto donde utiliza un iterador).


He editado el 'normal' para bucle de tal manera que es mucho menos idiomática, pero que tiene el mismo código de bytes como el bucle for mejorado. Para todos los efectos, la versión normal del ciclo for es lo que el compilador genera cuando compila el mejorado para cada ciclo.

+0

¡Whoa! ¡Muchas gracias! – SapphireSun

3

Sí, hay algo parecido al operador de C++ sizeof - es la variable length ejemplo El campo length (que da el número de elementos de la matriz, no el tamaño en bytes.) es siempre un miembro público de la matriz, por lo que es accesible para los programadores de Java.

Y sí, las matrices son objects, y no solo internamente.

(En términos más generales, la sintaxis for bucle funciona tal como se describe en el question que org.life.java vinculada a, pero eso no es exactamente lo que está pidiendo.)

Cuestiones relacionadas