Comprender el Control de Flujo Avanzado Hasta ahora, hemos estado tratando con bucles individuales que sólo terminan cuando su expresión booleano es evaluada como falsa . Ahora le mostraremos otras formas que podrían terminar el bucle , o la rama ,y verá que el camino recorrido durante el tiempo de ejecución puede no ser tan sencillo como en anteriores ejemplos. Bucles anidados En primer lugar , los bucles pueden contener otros bucles . Por ejemplo , considere el siguiente código que itera a través de una matriz de dos dimensiones , una matriz que contiene otras matrices así como sus miembros .Cubriremos las matrices multidimensionales en detalle en el capítulo 3 , pero por ahora asuma que lo siguiente es cómo se declare una matriz bidimensional . int[][] myComplexArray = {{5,2,1,3},{3,9,8,9},{5,7,12,7}}; for(int[] mySimpleArray : myComplexArray) { for(int i=0; i<mySimpleArray.length; i++) { System.out.print(mySimpleArray[i]+"\t"); } System.out.println(); } Nótese que mezclamos intencionadamente un for y un for-each en este ejemplo .El bucle exterior se ejecuta un total de tres veces . Cada vez que el bucle exterior se ejecuta, el bucle interior se ejecuta cuatro veces. Cuando se ejecuta este código , vemos el siguiente resultado : 5 3 5 2 9 7 1 8 12 3 9 7 Los bucles anidados pueden incluir while y do-while , como se muestra en este ejemplo . Determinar que salida da este código. int x = 20; while(x>0) { do { x -= 2 } while (x>5); x--; System.out.print(x+"\t"); } La primera vez este bucle se ejecuta , el bucle interno se repite hasta que el valor de x es 4. El valor será entonces decrementado a 3, y será la salida al final de la primera iteración del bucle exterior . En la segunda iteración del bucle exterior , el interior do-while se se ejecutará una vez , a pesar de que X ya no es mayor que 5. Como se recordará , do-while siempre ejecutan el cuerpo al menos una vez . Esto reducirá el valor a 1 ,que se reducirá aún más por el operador de decremento en el bucle externo a 0. Una vez que el valor alcance 0 , el bucle externo terminará. El resultado del código será el siguiente: 3 0 Adición de etiquetas opcionales Una cosa que se saltó cuando presentamos if-them , switch, y los bucles es que todos ellos pueden tener etiquetas opcionales . Una etiqueta es un puntero opcional a la cabeza de una declaración que permite que el flujo de la aplicación salte a ella o rompa desde ella . Es una sola palabra seguida de dos puntos ( :) . Por ejemplo , podemos añadir etiquetas opcionales para uno de los anteriores ejemplos: int[][] myComplexArray = {{5,2,1,3},{3,9,8,9},{5,7,12,7}}; OUTER_LOOP: for(int[] mySimpleArray : myComplexArray) { INNER_LOOP: for(int i=0; i<mySimpleArray.length; i++) { System.out.print(mySimpleArray[i]+"\t"); } System.out.println(); } Cuando se trata de un solo bucle , no añaden ningún valor , pero como veremos en la siguiente sección ,son extremadamente útiles en entornos anidados.Las etiquetas opcionales se utilizan a menudo solamente en estructuras de bucle . Si bien este tema no está en el examen de OCA , es posible añadir etiquetas opcionales para estructuras de control y bloques . Dicho esto , es raro que se considera una buena práctica de codificación hacerlo. Para el formato, las etiquetas siguen las mismas reglas que los identificadores . Para facilitar la lectura , son comúnmente expresados en mayúsculas , con guiones entre palabras , para distinguirlos de las variables regulares. La sentencia break Como se vio cuando se trabaja con las instrucciones switch , una sentencia break transfiere el control de flujo fuera de la declaración de encerramiento . Lo mismo es cierto para las sentencias break que aparecen en el interior de while, do-while , y para los bucles , ya que terminará el bucle,como se muestra en la Figura 2.9 FIGURA 2 . 9 Estructura de una sentencia break Observe en la figura 2.9 que la sentencia break puede tomar de parámetro una etiqueta opcional . Sin una etiqueta de parámetro, la sentencia break finalizará el bucle interno más cercano en el proceso de ejecución . El parámetro de etiqueta opcional permite salir de un bucle externo de nivel superior . En el siguiente ejemplo , buscamos las primeras ( x, y ) posiciones de índice de un array de un número dentro de una matriz de dos dimensiones no clasificada: public class SearchSample { public static void main(String[] args) { int[][] list = {{1,13,5},{1,2,5},{2,7,2}}; int searchValue = 2; int positionX = -1; int positionY = -1; PARENT_LOOP: for(int i=0; i<list.length; i++) { for(int j=0; j<list[i].length; j++) { if(list[i][j]==searchValue) { positionX = i; positionY = j; break PARENT_LOOP; } } } if(positionX==-1 || positionY==-1) { System.out.println("Value "+searchValue+" not found"); } else { System.out.println("Value "+searchValue+" found at: " + "("+positionX+","+positionY+")"); } } } Cuando se ejecuta, el código sería: Value 2 found at: (1,1) En particular , echar un vistazo al break PARENT_LOOP. Esta declaración romperá de toda la estructura de bucle , tan pronto como se encuentra el primer valor . Ahora , imaginemos¿qué pasaría si sustituimos el cuerpo del bucle interno con lo siguiente: if(list[i][j]==searchValue) { positionX = i; positionY = j; break; } ¿Cómo cambiaría esto nuestras flujo y cambiaría la salida ? En lugar de salir cuando el primer valor coincidente se encuentra , el programa ahora solo saldrá del bucle interno cuando se cumple la condición . En otras palabras, la estructura ahora hallará el primer valor coincidente de el último bucle interno para contener el valor , dando como resultado lo siguiente: Value 2 found at: (2,0) Por último , si hemos eliminado la ruptura por completo ? if(list[i][j]==searchValue) { positionX = i; positionY = j; } En este caso , el código buscará el último valor de toda la estructura que tiene elvalor coincidente . La salida tendrá el siguiente aspecto : Value 2 found at: (2,2) Se puede ver en este ejemplo que usar una etiqueta en una sentencia break en un bucle anidado, o no usar la la sentencia break en absoluto, puede hacer que la estructura de bucle se comporte de manera muy diferentemente. La sentencia continue Ahora vamos a completar nuestro análisis de control de bucle avanzado con la sentencia continue , una declaración que hace que el flujo termine la ejecución del bucle , como se muestra en la Figura 2.10 . FIGURE 2 .10 The structure of a continue statement Usted puede notar que la sintaxis de la instrucción continue refleja la de la sentencia break .De hecho,las sentencias son similares en la forma en que se utilizan , pero con diferentes resultados.Mientras que la sentencia break transfiere el control a la sentencia que encierra , continue transfiere el control a la expresión booleana que determina si el bucle debe continuar. En otras palabras , se termina la iteración actual del bucle. También como break, continue se aplica al bucle interno más cercano en ejecución usando etiquetas opcionales para modificar este comportamiento . Vamos a echar un vistazo al siguiente ejemplo: public class SwitchSample { public static void main(String[] args) { FIRST_CHAR_LOOP: for (int a = 1; a <= 4; a++) { for (char x = 'a'; x <= 'c'; x++) { if (a == 2 || x == 'b') continue FIRST_CHAR_LOOP; System.out.print(" " + a + x); } } } } Con la estructura tal como se define , el bucle devolverá el control al bucle padre en el momento que el primer valor es 2 o el segundo valor es b . Esto resulta en una ejecución del bucle for-each interior por cada tres llamadas de bucle exteriores . La salida es el siguiente : 1a 3a 4a Ahora , imaginemos que hemos eliminado la etiqueta FIRST_CHAR_LOOP en la sentencia continue para que continúe se devuelva el control al bucle interior en lugar del exterior . Ver si se puede entender cómo la salida será cambiada a: 1a 1c 3a 3c 4a 4c Por último , si quitamos la sentencia continue y las sentencias if-then asociadas por completo ,llegamos a una estructura que da salida a todos los valores , tales como : 1a 1b 1c 2a 2b 2c 3a 3b 3c 4a 4b 4c La Tabla 2.5 le ayudará a recordar cuando las etiquetas , break, y contiune estan permitidas en Java . Aunque con fines ilustrativos nuestros ejemplos han incluido el uso de estas sentencias en bucles anidados , pueden ser utilizadas dentro de los bucles individuales también. TABLE 2.5 Uso de control de flujo avanzado * Las etiquetas están permitidas para cualquier sentencia de bloque , incluyendo los que están precedidos con una sentencia if-then .