El bucle for en Java (y for-each)

El bucle for en Java, junto con su primo el for-each,  son estructuras lógicas que te permiten realizar una y otra vez una acción, siempre y cuando se cumpla una condición booleana.

More...

En el artículo de hoy vamos a ver cómo se utilizan ambas estructuras, y veamos qué trampas nos podemos encontrar en el examen de certificación OCAJ8P.

Bucles for y for-each en Java: qué son y cómo se comen

Los bucles for y for-each en Java son dos maneras de realizar bucles. Aunque su nombre es similar, su estructura es diferente. Con el bucle for tienes más control en la ejecución del bucle. 

Estructura del bucle for en Java

El bucle for en Java toma como punto de partida un índice de control. Al final de cada bucle, este índice se actualiza según una regla que estableces en la estructura del bucle. Acto seguido, el bucle comprueba si el índice satisface la condición booleana.

El bucle for comienza con la palabra clave for y un paréntesis, que contiene tres partes.

Índice de control

Bucle for en Java: índice de control

El índice de control, si fuera un avión de combate

El índice de control, que tradicionalmente te lo encontrarás representado con la variable i de tipo int, puede en realidad tomar cualquier valor; no hace falta ni siquiera que tenga un valor numérico (aunque habitualmente sea un int):

En cualquier caso, no es necesario que declares la variable (o referencia) que utilices como valor de control dentro del paréntesis; puedes utilizar una variable o referencia que exista con anterioridad:

No obstante, si declaras el índice de control en el paréntesis, solo podrás utilizar esta variable o referencia dentro del bucle for.

Condición booleana

Bucle for en Java: evaluación booleana

La condición booleana, si fuera un señor con lupa

La condición booleana simplemente evalúa si el índice de control tiene, o no, un valor determinado. Si quieres saber más sobre la condición booleana, no dudes en echarle un ojo al artículo que escribí al respecto.

El bucle se continúa ejecutando siempre y cuando el resultado de la evalución sea true.

Actualización del índice de control

Bucle for en Java: un camello feo

Actualización del índice, si fuera un camello dentudo

La tercera parte de la estructura del bucle for en Java consiste en una regla según la cual el índice de control se va a actualizar después de cada iteración. Por ejemplo, se puede sumar una unidad o, como en el muy complicado primer ejemplo que te he puesto, actualizar la String utilizada como control, agregándole un char (es un caso extremo, que no creo que te encuentres nunca. Por lo menos, fuera del examen).

Un bucle for en Java puede tener un número ilimitado de índices de control

Un bucle for puede contener tantos índices de control como sea necesario, pero todos han de ser del mismo tipo. En este caso, la evaluación booleana puede ser más larga, de manera que se evalúen de manera simultánea todos los índices. En la tercera parte de la estructura del bucle, se puede hacer una lista de todas las reglas de actualización de los índices de control:

Qué has de tener en cuenta a la hora de examinar un bucle for en Java

La flexibilidad a la hora de construir un bucle for en Java es tan grande, que puedes prescindir de algunas de las partes de las que te acabo de hablar. Por ejemplo, también puedes establecer una evaluación  booleana que siempre sea true. Como consecuencia, el bucle no deja nunca de ejecutarse hasta que el programa se detiene con un error por falta de memoria.

Todo está permitido, con tres condiciones:

  • Los tres elementos van separados por ; (punto y coma) en cualquier caso. 
  • Si alguno de los elementos no está presente, los dos puntos y comas han de aparecer de todas formas.
  • El índice de control ha de existir (se ha de haber declarado, ya sea antes del bucle for o en la primera parte del paréntesis del bucle)
Ejemplos de bucles for válidos

En el siguiente ejemplo te muestro varios ejemplos de bucles en los que falta alguno de los elementos (o todos ellos). Recuerda que, para ejecutar los bucles de este ejemplo, necesitas hacerlo por separado El primer bucle for es un bucle infinito, y no va a permitir la ejecución del resto.

Fíjate que en bucle nº 5: aunque el código contenido en el bucle no se llega a ejecutar, el código compila. Esto se debe a que el compilador no sabe cuál es el valor de la variable. Mejor dicho, sabe que la variable se ha iniciado con un valor, pero no "recuerda" qué valor es este. La única manera de hacer que el compilador tenga en cuenta el valor de la variable es utilizando la palabra clave final. Pero entonces surge otro problema:

Dado que cualquier variable marcada como final es invariable, el código no compila, ya que l++ no es legal. Si el índice de control fuera una referencia a un objeto, en lugar de una variable primitiva, final no permite que la referencia se asigne a un nuevo objeto, pero sí permite que el objeto se modifique:

¿Qué ocurre si utilizas directamente los valores true o false en la evaluación?

A diferencia de lo que ocurría si utilizabas false en un if, que era perfectamente válido, no puedes utilizar false en un bucle for en Java, aunque el bucle esté vacío:

El uso de true crea un bucle infinito, ya que la evaluación nunca llega a tener el valor false.

Por último, un bucle for en Java puede prescindir de las llaves, si el código que contiene consta de una sola línea (hasta el primer punto y coma). Vigila la posición del bucle for en ese caso:

El compilador no tiene en cuenta los espacios en blanco, así que lo que ve es: for(;;)}. Después de cerrarse el paréntesis no puede cerrarse una llave.

Orden de ejecución de cada una de las partes de la estructura

Esta parte la has de tener muy clara. Imagínate, por ejemplo, que instancias el índice de control fuera del bucle. Así, tienes acceso a él una vez finalizado este. ¿Sabes qué valor ha adquirido el índice, y por qué?

Este es el orden de ejecución de cada una de las partes de la estructura:

  • En primer lugar, se instancia el índice de control, o toma el valor, si le determinas uno nuevo. 
  • A continuación, se evalúa el índice de control. Si la evaluación es falsa, el bucle se detiene.
  • Si la evaluación es verdadera, se ejecuta el código del bucle for.
  • Una vez ejecutado, se modifica el valor del índice de control según la regla establecida.
  • Se vuelve a evaluar el índice de control.

¿Qué crees que imprimirá el siguiente código? El resultado lo tienes más abajo.

El código no se ejecuta, ya que la variable i se ha declarado en el bucle y no se puede acceder a ella desde fuera de este.

Bucles for anidados

Los bucles for anidados consisten en crear un bucle for dentro de otro bucle. Son útiles si quieres, por ejemplo, imprimir el contenido de un array de dos dimensiones:

Más abajo te hablo del bucle for-each, más cómodo para iterar por una lista.

Cómo hackear un bucle: continue/break

Las palabras clave continue y break sirven para hackear la ejecución de cualquier bucle en Java.

Continue, o pasa a la siguiente iteración

La palabra clave continue detiene la ejecución del código en el bucle, y fuerza a que este pase a su siguiente iteración.

Como ves, cuando el valor de i es 3 se cumple la condición del bloque if. Se ejecuta la orden continue y el bucle pasa a su siguiente iteración, es decir, siendo cuatro el valor de i.

Ten en cuenta que el bucle sigue funcionando con normalidad. Si el siguiente valor de i diera como resultado false en la evaluación booleana, la ejecución del código saldría del bucle.

El código tras continue no se ejecuta, asi que este o es la última condición dentro de un if, o el código no compila. Un continue al final del bucle no cambia nada.

Break, o "rompe" el bucle

La palabra clave break detiene de inmediato la ejecución del bucle. Al igual que continue, ha de ser la última condición dentro de un if. Puede aparecer por sí sola al final del bucle, pero en ese caso el bucle se ejecutará solo una vez:

Bucles for anidados con break, continue y etiquetas

Aquí juntamos los bucles anidados que te he enseñado antes, con las palabras clave break y continue. Suponte, por ejemplo, que quieres que el hilo de ejecución abandone todo el complejo de bucles, si el índice de control de un bucle for anidado toma un valor determinado.

En ese caso, puedes utilizar una etiqueta. Las etiquetas son similares a puntos de anclaje, a los que puedes hacer referencia para que, al ejecutarse un break, el hilo de ejecución continúe a partir de dicho punto de anclaje. Quedará más claro con un ejemplo:

Como ves, cuando se ejecuta el break con la etiqueta el hilo de ejecución NO vuelve a entrar en el bucle aunque la etiqueta se encuentre justo antes de este.

En el siguiente ejemplo utilizo el mismo código, pero con continue en lugar de break:

¿Eres capaz de seguir la ejecución, según el resultado obtenido?

Estructura de las etiquetas

Para que una etiqueta sea válida, ha de seguir una serie de reglas.

  • Para empezar, el nombre de la etiqueta ha de seguir las reglas de Java para la creación de nombres. Como dice la página oficial de Oracle,  en Java un nombre consta de una cadena, de cualquier longitud, de caracteres Unicode. El primer caracter del nombre solo puede ser una letra, el símbolo del dolar ($), o un guion bajo (_).
  • Una etiqueta puede existir por sí sola, sin ningún break o continue que haga referencia a ella.
  • Para que una referencia a una etiqueta sea válida, la etiqueta tiene que encontrarse justo antes de un bucle. El break o continue que haga referencia a esta etiqueta ​se ha de encontrar dentro de ese mismo bucle.
  • La etiqueta precisa de dos puntos al final (primero:). Un break o continue con etiqueta necesita un espacio antes de la etiqueta (break primero; o continue primero;)

El bucle for-each en Java

El bucle for-each en Java se utiliza para iterar a lo largo de una lista de objetos o variables primitivas. Es decir que, para el examen de certificación OCAJ8P, se utilizará para objetos de tipo List, ArrayList y para array[], tanto de objetos como de variables primitivas.

En este tipo de bucle no tienes tanto control como en el bucle for que acabamos de ver.

Estructura del bucle for-each

La estructura de este bloque es muy básica. Se compone, de nuevo, de la palabra clave for seguida de un paréntesis. Este contiene tres partes, pero que son más sencillas que las del bucle for anterior.

  • Para empezar, aparece el tipo del objeto que se va a extraer, o el tipo de la variable primitiva (en caso de que se trate de un array[]).
  • A continuación, el nombre que recibe la variable o referencia local, con la que va a operar el bucle.
  • Por último, el nombre de la lista de la que vamos a extraer los componentes.

No se puede prescindir de ninguna de las tres partes.

Aquí tienes un ejemplo más gráfico de la estructura del for each:

Como puedes ver, el único símbolo que aparece dentro del paréntesis son los dos puntos (:) que separan el nombre de la variable local del nombre de la lista que vamos a iterar.

Bucles for-each anidados

Recuerda que, si el array tiene más de una dimensión, la variable local será también un array, pero con una dimensión menos. A continuación te muestro una serie de bucles for-each anidados, partiendo de un array de tres dimensiones. Como ves, conforme vamos avanzando, el array iterado tiene un dimensión menos que su padre. ¿Adivinas por qué?

Con el bucle for en Java tienes la posibilidad de controlar el bucle de muchas maneras. Puedes, por ejemplo, controlar cuántas veces puede ejecutarse. O incluso hacer que, si itera una lista, se salte un elemento. Esto se consigue, por ejemplo, modificando el índice de control de manera que con cada bucle se sumen dos unidades, en lugar de una (i += 2). El bucle for-each está creado de manera específica para iterar listas. Viene a ser un bucle for resumido, con una función específica.

Debido a esta limitación, no te rompas la cabeza si necesitas un control más fino del bucle: utiliza un for clásico,  y ya está.

Break y continue en un for-each

El uso de break y continue, tanto por sí solos como con etiquetas, es exactamente igual al uso que hemos visto más arriba en un bucle for normal:

Ejercicios recomendados

Construye bucles for y for-each anidados muy complejos, que te fuercen a seguirlos línea a línea con papel y lapiz. Puedes ejercitar los siguientes puntos:

  • Crea un bucle for con varios índices de control. Comprueba si puedes reutilizar una variable ya inicializada fuera del bucle, y otra que inicies en el bucle.
  • No olvides practicar las evaluaciones booleanas, sobre todo con los operadores & y |. Estos evalúan la otra parte de la condición, aunque sea innecesario. Esto se puede traducir en modificaciones del valor de las variables.
  • Si te estás preparando el examen, no es necesario que utilices nombres de variables adecuados. En el examen tampoco lo van a ser.

¿Qué problemas te han surgido? ¿has aprendido u observado algún detalle que me haya dejado yo en el tintero? ¡Espero tus comentarios!

Los recursos con los que yo superé el OCA con una puntuación del 92%

Si estás en serio con la programación en Java, te recomiendo dos recursos esenciales: el manual de Java que te muestro a la izquierda, y los exámenes de práctica de Enthuware. Son los que yo utilicé para obtener un 92% de puntuación.

También existen cursos en español en Udemy, y en inglés en Skillshare, Lynda y Udacity (en este último, gratuitos). Échale un vistazo al apartado Recursos para Java.

Sección de comentarios cerrada