2012-02-16 18 views
14

Me pregunto si el siguiente ciclo crea una copia del objeto, en lugar de darme una referencia. La razón es porque el primer ejemplo no asigna mis objetos de matriz, pero el segundo sí.Java: For-Each loop y referencias

MyObject objects[] = new MyObject[6]; 
for (MyObject o: objects) { 

    o = new MyObject(); 
} 

MyObject objects[] = new MyObject[6]; 
for(int i = 0; i < objects.length; i++) { 

    objects[i] = new MyObject(); 
} 
+0

¿Existe realmente una sintaxis de bucle for como la primera está presente en java? –

+0

@ChandraSekhar: [for-each loop java] (http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html). – RanRag

+0

@ChandraSekhar RanRag tiene razón. Sin embargo, eso no es relevante para la pregunta.Tal vez el OP simplemente reescribió su código, no copió/pegó y, por lo tanto, pensó en su idioma preferido. –

Respuesta

15

Java funciona un poco diferente a muchos otros idiomas. Lo que o está en el primer ejemplo es simplemente una referencia al objeto.

Cuando dice o = new MyObject(), se crea un nuevo objeto de tipo MiObjeto y referencias o a ese objeto, mientras que antes referenciada oobjects[index].

Es decir, objects [index] en sí es solo una referencia a otro objeto en la memoria. Por lo tanto, para establecer objetos [índice] en un nuevo objeto MyObject, debe cambiar hacia dónde apuntan los objetos [índice], lo cual solo se puede hacer usando objetos [índice].

la imagen: (mis habilidades de pintura terribles: D)

enter image description here

Explicación: Esto es más o menos cómo funciona la gestión de memoria de Java. No exactamente, de ninguna manera, sino aproximadamente. Usted tiene objetos, que hace referencia a A1. Cuando accede a la matriz de objetos, comienza desde el punto de referencia inicial (A1) y avanza X bloques. Por ejemplo, hacer referencia al índice 1 lo llevaría a B1. B1 luego te dice que estás buscando el objeto en A2. A2 te dice que tiene un campo ubicado en C2. C2 es un número entero, un tipo de datos básicos. La búsqueda está hecha.

o no hace referencia a A1 o B1, pero C1 o C2. Cuando diga new ..., creará un nuevo objeto y lo colocará allí (por ejemplo, en el espacio A3). No afectará a A1 o B1.

Avísame si puedo aclarar un poco las cosas.

+0

Claro, eso hace sentir. Entonces, en el primer ejemplo, o es un poco como un puntero de C++, en el sentido de que es en sí mismo una variable, y por lo tanto su valor es la dirección de otra variable. Por lo tanto, al asignarle algo, se establece la variable, en lugar de lo que apunta. Gracias! – rhughes

+0

Exactamente: D A diferencia de C++, Java no tiene mucho en el camino de los controles de punteros y tal. Las variables de referencia se colocan en la memoria, y '=' las re-referencias. No puedes crear una nueva variable a la que te refieres. Sin embargo, puedes cambiar esta variable. Si 'o' ya está inicializado y' o.x' es un campo, puede cambiar dónde 'o.x' apunta, reasignando' o.x'. –

3

La primera no es la asignación de la matriz de objetos porque foreach bucles iterar sobre los elementos de una colección.

Cuando ingresa ese bucle foreach no tiene ningún elemento en su colección, es solo una matriz vacía inicializada al tamaño 6, por lo que no se agregarán objetos a su matriz.

Además, tenga en cuenta que incluso si tuviera elementos de la matriz del bucle foreach no asignaría sobre la parte superior de ellos:

o = new MyObject(); 

básicamente significa asignar a o una nueva instancia de MyObject, pero sí no es o parte de la matriz objects es solo un contenedor temporal usado para iterar sobre los elementos de la matriz, pero en este caso, no hay ninguno.

+0

No está realmente vacío, solo tiene 6 nulos dentro. De lo contrario, buena respuesta. +1 –

+0

vacío en el sentido de que no hay elementos de 'MyObject' dentro de él. –

+0

Creo que estamos diciendo lo mismo en diferentes palabras. –

8

respuesta corta: sí, hay algo así como una copia pasando.

El respuesta larga: El bucle foreach Java informados es el azúcar sintáctica para

MyObject objects[] = new MyObject[6]; 

Iterator<MyObject> it = objects.iterator(); 
while (it.hasNext()) { 
    MyObject o = it.next(); 
    // The previous three lines were from the foreach loop 

    // Your code inside the foreach loop 
    o = new MyObject(); 
} 

como la versión espectáculos Desazucarado, establecer una referencia igual a algo dentro de un bucle foreach no cambia el contenido de la formación.

2

Los objetos solo se "copian" cuando usted declara explícitamente que desea clonar un objeto (y este objeto implementa explícitamente la característica de clonación).

Parece que confunde referencias y nombres.

En el primer ejemplo, dentro de un foreach, la variable local o se refiere al área de memoria en la que se almacena algún objeto desde objects. Cuando está haciendo o = new MyObject(), un nuevo MyObject se inicializa en algún otro área de la memoria, y luego la referencia o se reescribe para apuntar a esta nueva área de la memoria.

En el segundo ejemplo, escribiendo objects[i] = new MyObject(), está diciendo que se debe volver a escribir la referencia objects[i], no alguna variable local o.

4

He añadido un comentario a cada ejemplo para aclarar lo que está sucediendo.

Primer ejemplo:

MyObject objects[] = new MyObject[6]; 
for(MyObject o: objects) { 

    // Construct a new object of type MyObject and assign a reference to it into 
    // the iteration variable o. This has no lasting effect, because the foreach 
    // loop will automatically assign the next value into the iteration variable 
    // in the the next iteration. 
    o = new MyObject(); 
} 

Segundo ejemplo:

MyObject objects[] = new MyObject[6]; 
for(int i = 0; i < objects.length; i++) { 

    // Construct a new object of type MyObject and store a reference to it into the 
    // i-th slot in array objects[]: 
    objects[i] = new MyObject(); 
} 
+0

No compilará en absoluto, ya que no es una palabra clave en java, debe colocar dos puntos (:) allí. –

+0

Acabo de copiar el código original del usuario antes de editarlo y me lo perdí. Dicho eso, no cambia el punto de mi respuesta. –

+0

Quien diga "Igor" debería decir por qué lo hicieron. La retroalimentación negativa no sirve de nada si no ofrece una explicación de las mejoras. Igor, sospecho que tuviste -1 debido a la falta de profundidad. –

0

La primera cosa que quiero mencionar es que las matrices no son siempre cero longitud mutable.And dentro del bucle foreach

for(MyObject o in objects) 

lo que hace es en cada iteración funciona de la siguiente manera.

o = objects[0] // first iteration 
o = objects[1] // 2nd iteration 

Pero en su caso, se asigna otro objeto de la referencia o. No a los objetos en la matriz. Simplemente le gusta seguir.

ObjeMyObject objects[] = new MyObject[6]; 
MyObject o = Object[0]; 
0 = new MyObject(); 

Pero sus objetos originales [0] aún apuntan a un objeto nulo.

0

Cada vez que utiliza el operador "nuevo", JVM creará una nueva instancia y se asignará al operando del lado izquierdo del operador de asignación. no importa en cada bucle o bucle. En para cada bucle para (MyObject O: Object) O se creará una vez solamente que serán de MyObject no será instanciada y los valores de la matriz objeto será mantener la copia en O como

O = Object[0] 
O = Object[1] 
O = Object[2] 
O = Object[3] 
O = Object[4] 
O = Object[5] 

No necesitamos mejorar el contador, esta es la belleza de cada ciclo.