paneles definicion create java loops foreach syntactic-sugar

definicion - paneles java swing



Java para cada vs regular para-son equivalentes? (4)

¿Son estos dos constructos equivalentes?

char[] arr = new char[5]; for (char x : arr) { // code goes here }

Comparado con:

char[] arr = new char[5]; for (int i = 0; i < arr.length; i++) { char x = arr[i]; // code goes here }

Es decir, si pongo exactamente el mismo código en el cuerpo de ambos bucles (y se compilan), ¿se comportarán exactamente igual?

Descargo de responsabilidad completo: esto se inspiró en otra pregunta ( Java: si estos 2 códigos son iguales ). Mi respuesta allí resultó no ser la respuesta, pero creo que la semántica exacta de Java para cada uno tiene algunos matices que deben destacarse.


El primero es más legible y, por lo tanto, más preferible, si va a necesitar el índice de todos modos, entonces rellene el segundo.


Mientras que a menudo las dos construcciones son intercambiables, ¡¡¡ NO SON 100% EQUIVALENTES !!!

Se puede construir una prueba definiendo // code goes here que haría que las dos construcciones se comporten de manera diferente. Un tal cuerpo de bucle es:

arr = null;

Por lo tanto, ahora estamos comparando:

char[] arr = new char[5]; for (char x : arr) { arr = null; }

con:

char[] arr = new char[5]; for (int i = 0; i < arr.length; i++) { char x = arr[i]; arr = null; }

Ambos códigos se compilan, pero si los ejecutas, encontrarás que el primer bucle termina normalmente, mientras que el segundo bucle arrojará una NullPointerException .

Esto significa que no son 100% equivalentes! ¡Hay escenarios donde las dos construcciones se comportarán de manera diferente!

Es probable que estos escenarios sean raros, pero este hecho no debe olvidarse al depurar, ya que de lo contrario es posible que se pierdan algunos errores realmente sutiles.

Como anexo, tenga en cuenta que a veces la construcción for-each no es una opción, por ejemplo, si necesita el índice. La lección crucial aquí es que incluso si es una opción, debe asegurarse de que sea un sustituto equivalente, porque no siempre está garantizado.

De manera similar, si comienza con un bucle para cada uno y luego se da cuenta de que necesita cambiar al bucle indexado, asegúrese de que está preservando la semántica, porque no está garantizado .

En particular, _se desconfíe de cualquier modificación a la referencia de la matriz / colección que se está iterando_ (la modificación del contenido puede / no puede desencadenar ConcurrentModificationException , pero eso es un problema diferente).

Garantizar la preservación de la semántica también es mucho más difícil cuando se usan colecciones que usan iteradores personalizados, pero como muestra este ejemplo, las dos construcciones son diferentes incluso cuando se trata de matrices simples.


Son prácticamente equivalentes . Pero puede haber pocos casos donde no lo sean. Lo mejor es hacerlo final .

final char[] arr = new char[5]; // Now arr cannot be set null as shown // in above answer.

Incluso entonces puedes hacer i-- en el segundo bucle. Si no haces algunas de estas cosas poco probables, son en su mayoría equivalentes.


Tenga en cuenta que la diferencia más importante está implícita en la respuesta que dieron "polygenelubricants", pero no se establece explícitamente: para cada iteración a través de la matriz, pero no puede modificar ninguno de los elementos utilizando la instancia que le brinda el ciclo (en En este caso, la variable "char x"). El bucle clásico le permite usar el índice y alterar un elemento de la matriz.

Edición: corrección rápida.