6.2 Creating Loops Constructs - ajpaez/OCA GitHub Wiki
(OCA Objectives 5.1, 5.2, 5.3, 5.4, and 5.5)
Los bucles java se presentan de tres formas distintas: while, do y for ( y desde Java 5 el bucle for tiene dos variantes). Los tres permiten repetir un bloque de código, siempre y cuando se cumpla una condición.
Usando bucles while
El bucle while es bueno cuando no se conoce la cantidad de veces que un bloque de código debe de repetirse, pero quiere que se repita hasta que se cumpla una condición sea true, estructura:
while (expression) {
// do stuff
}
En este caso, como en el resto de los bucles, la expresión (expression) debe de ser evaluada con un resultado boleano true para que se ejecute el cuerpo del bucle.
Cualquier variable usada para la expresión de un bucle while debe de ser declarada antes de ser la expresión evaluada: while ( int x = 2 ) { ... } // not legal
El punto clave a recordar es que un bucle while puede no ejecutarse nunca, si la expresión es false a la hora de evaluarla, el bucle se omite.
Usando bucles do
El bucle do es similar al bucle while, excepto que este garantiza que siempre se ejecuta al menos una vez su bloque de codigo y posterioremente se comprueba la condicion, ejemplo:
do {
System.out.println("Inside loop");
} while(false);
¡¡¡ Ojo con el punto y coma final !!!
Usando bucles for
Bucle for básico
El bucle for basico es util cuando el control del flujo cuando conocemos el numero de veces que necesiamos repertir el bloque de codigo. El bucle for tiene tres partes principales, ademas del cuerpo del bucle:
- Declaracion e inicializacion de varialbes
- Expresion ( test condicional)
- Expresion de iteracion
Estas tres partes estan separadas por punto y coma (;).
Estructura y ejemplo:
for (/*Initialization*/ ; /*Condition*/ ; /* Iteration */) {
/* loop body */
}
for (int i = 0; i<10; i++) {
System.out.println("i is " + i);
}
Bucle for básico: declaración e inicialización
La primera parte de la cabecera del bucle es donde se declaran e inicializan, ninguna, una o muchas variables a la vez, pero todas del mismo tipo dentro de paréntesis. Si se necesita declarar varias variables deben de separarse con comas de la siguiente forma: for (int x = 10, y = 3; y > 3; y++) { } La declaración e inicialización es lo primero que se ejecuta y al contrario de las otras dos partes que se ejecutan en cada racionero, esta primera parte solo se ejecuta una sola vez, al principio.
Bucle for básico: Expresión (boleana) condicional
La segunda parte de la cabecera es la expresión del bucle for, que (al igual que otros test condicionales) deben de evaluar un valor booleano. Un bucle for solo puede tener una expresion boolean, pero puede ser tan compleja como se desee:
for (int x = 0; ((((x < 10) && (y-- > 2)) | x == 3)); x++) { } // ok
for (int x = 0; (x > 5), (y < 2); x++) { } // ilegal!, too many expressions
Bucle for básico: Expresión de iteración
Como tercer componente, tenemos la expresión de iteración, esta es ejecutada antes de la ejecución del cuerpo del bucle. Después de la ejecución del cuerpo del bucle, la expresión de iteración se ejecuta de nuevo y a continuación, se comprueba la expresión condicional.
Bucle for básico: mejoras del bucle
Ninguna de las tres partes antes habladas es requerida. El ejemplo sigueinte es perfectamente legal:
for( ; ; ) {
System.out.println("Inside an endless loop");
}
Para el examen es necesario saber que un bucle for con la ausencia de las partes de iniclaizacion e incremento, dicho bucle actua como un bucle while, por ejemplo:
int i = 0;
for (;i<10;) {
i++;
// do some other work
}
// que sería igual que...
int i = 0;
while(i<10) {
i++;
// do some other work
}
Cabe destacar también que cada una de las secciones de la cabecera de un bucle for son independientes la una de la otra, no es necesario que las tres secciones operen sobre las mismas variables. Pero incluso la expresión del iterador, no necesariamente tiene que incrementar ni establecer ninguna variable, puede ejecutar prácticamente cualquier sentencia de código arbitrario para que suceda en cada iteración, por ejemplo, el siguiente for imprime dos veces la palabra iterate.
int b = 3;
for (int a = 1; b != 1; System.out.println("iterate")) {
b = b - a;
}
Bucle for mejorado (para Arrays)
El bucle for mejorado, se trata de un bucle for especializado que simplifica la forma de recorrer arrays o colecciones.Un bucle for mejorado necesita una matriz o un objeto de una clase que implemente java.lang.Iterable. Map no implementa Iterable, aunque puedes usar métodos keySet () o values () para obtener una Colección (que extiende Iterable) e iterar sobre esa Colección. En lugar de tener tres componentes el bucle for mejorado tiene dos:
for(declaration : expression)
- Declaración: Nueva variable a crear ( NO puede estar declarada antes) y con la que se accederá a los elementos de la colección, dicha variable solo está disponible desde dentro del bucle y su valor será el del elemento actual.
- Expresión: Será el array o colección que queremos recorrer, estas pueden ser de cualquier tipo: primitivas, objetos o incluso otros arrays.
int x;
long x2;
long [] la = {7L, 8L, 9L};
int [][] twoDee = {{1,2,3}, {4,5,6}, {7,8,9}};
String [] sNums = {"one", "two", "three"};
Animal [] animals = {new Dog(), new Cat()};
// legal 'for' declarations
for(long y : la ) ; // loop thru an array of longs
for(int[] n : twoDee) ; // loop thru the array of arrays
for(int n2 : twoDee[2]) ; // loop thru the 3rd sub-array
for(String s : sNums) ; // loop thru the array of Strings
for(Object o : sNums) ; // set an Object reference to
// each String
for(Animal a : animals) ; // set an Animal reference to each
// element
// ILLEGAL 'for' declarations
for(x2 : la) ; // x2 is already declared
for(int x2 : twoDee) ; // can't stuff an array into an int
for(int x3 : la) ; // can't stuff a long into an int
for(Dog d : animals) ; // you might get a Cat!
Rupturas de un bucle
Sentencia | Resultado |
---|---|
break | La ejecución salta inmediatamente a la primera instrucción después del bucle foor |
return | La ejecución salta inmediatamente al método que invoco al método donde se encuentra el bucle |
System.exit() | Se detiene toda la ejecución del programa, la maquina virtual se apaga |
Uso de break y continue
Las keywords break y continue son usadas para detener un bucle por completo (break) o simplemente la iteración actual (continue). Normalmente si se usa break o continue, será junto con un if.
La sentencia break hace que el programa detenga su ejecución en el bucle y comienza la ejecución de la siguiente linea de código después del bloque de código. La sentencia continue hace que solo la iteración actual en el bucle mas interno detenga su ejecución y la siguiente iteración del mismo bucle comience si se cumple la condición de dicho bucle. Cuando se use continué en un bucle foor, hay que tener presente los efectos que producirá dicha sentencia en la iteración actual del bucle, si esta aparece al final los efectos serán los mismos que si no existiese, por ejemplo:
for (int i = 0; i < 10; i++) {
System.out.println("Inside loop");
continue;
}
En cambio, si establecemos cualquier condición antes del final de la iteración y lanzamos un continue el resto del código de la iteración no se ejecutará:
for (int i = 0; i < 10; i++) {
System.out.println("Inside loop");
if (foo.doStuff() == 5) {
continue;
}
// more loop code, that won't be reached when the above if test is true
}
RECUERDA!! : continue debe estar dentro de un bucle y break dentro de un bucle o un switch, en otro caso el compilador lanzará un error.
+ Un break sin etiqueta transferir el control a la sentencia mas cercana al switch, while, do, o for actual; Esta declaración, que se denomina break target, se completa inmediatamente de forma normal. Si no existe ningun switch, while, do, o far como la instrucción que encierra la break, se produce un error en tiempo de compilación.
+ Una break con etiqueta Id intenta transferir el control a la declaración etiquetada adjunta que tiene el mismo identificador que su etiqueta; Esta declaración, que se denomina break target, se completa inmediatamente de forma normal. En este caso, el objetivo de ruptura no necesita ser una sentencia while, do, for o switch.
+ Un continue sin etiqueta intenta transferir el control al bucle interno que la encierra; Esta sentencia, que se denomina continue target, termina inmediatamente la iteración actual y comienza una nueva. Si ninguna sentencia while, do, o for incluye la sentencia continue, se produce un error en tiempo de compilación.
+ Un continue con la etiqueta Id intenta transferir el control a la declaración etiquetada adjunta que tiene el mismo identificador que su etiqueta; Esa sentencia, que se denomina continue target, termina inmediatamente la iteración actual y comienza una nueva. El objetivo de continuación debe ser un while, do, or for statement sino se produce un error en tiempo de compilación. Si ninguna declaración etiquetada con Id como su etiqueta contiene la instrucción continue, se produce un error en tiempo de compilación.
Declaraciones no etiquetadas
Tanto la instrucción break como continue pueden estar etiquetadas o no. Los ejemplos que se han mostrado anteriormente se tratan de sentencias no etiquetadas.
Declaraciones etiquetadas
Aunque muchas sentencias en Java pueden etiquetarse es mas común usar etiquetas en bucles junto con break y continue.
Una etiqueta debe estar declarada justo antes del bloque de código que se quiera etiquetar y consiste en un identificador que termina con dos puntos ( : ) .
Etiquetar un bucle es interesante cuando se presente una situación en la que existan varios bucles anidados y queramos romper la ejecución de alguno de ellos o desde cual de estos se desea continuar en la siguiente iteracion.
La declaración de una etiqueta debe adherirse a las mismas reglas que existen para el nombre de las variables y a las convenciones de Java.
boolean isTrue = true;
outer:
for(int i=0; i<5; i++) {
while (isTrue) {
System.out.println("Hello");
break outer;
} // end of inner while loop
System.out.println("Outer loop."); // Won't print
} // end of outer for loop
System.out.println("Good-Bye");
En este ejemplo la palabra Hello solo es pintada una vez, una vez hecho, la sentencia break rompe la ejecución de cualquier bucle y salta a la etiqueta outer, entonces se ejecutará el ultimo sysout.
Si sustituimos break por continue:
outer:
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++) {
System.out.println("Hello");
continue outer;
} // end of inner loop
System.out.println("outer"); // Never prints
}
System.out.println("Good-Bye");
Solo se detiene la iteración del bucle interno y continúan las iteraciones del exterior.
Hello Hello Hello Hello Hello Good-Bye