Saltar a contenido

6. Iteración: for clásico sobre arrays y Strings

UD3 — Control de Flujo y Depuración · RA3 — Escribe y depura código, analizando y utilizando las estructuras de control del lenguaje

IES Thiar — Pilar de la Horadada (Alicante) · Curso 2026-2027

Aspecto Valor
Resultado de aprendizaje RA: 3 — Escribe y depura código, analizando y utilizando las estructuras de control del lenguaje.
Criterios de evaluación a los que contribuye esta sección CE 3.2 (utiliza estructuras de repetición)
CE 3.5 (crea programas ejecutables combinando estructuras de control)
CE 3.7 (comenta y documenta el código).
Marco normativo RD 405/2023 · RD 450/2010 · RD 659/2023
Tecnología base Java 25 LTS (OpenJDK Temurin 25) — soporte hasta 2030+
Horas estimadas ~2 h (de las 30 h de la UD3).

Requisitos previos (lo que ya sabes): condiciones booleanas y operadores lógicos (sección 1 de UD3); if / else if / else, early return, validación con IO.readln y String.matches (sección 2 de UD3); switch expression con flecha y múltiples etiquetas (sección 3 de UD3); while y do-while (sección 4 de UD3); arrays unidimensionales como tipo compuesto (declaración con { } y con new Tipo[n], .length, acceso por índice, valores por defecto, String.toCharArray(), swap) — todo eso se introdujo en la sección 5 de UD3. Importante: en la sección 5 se introdujo el tipo array en sí, pero no se recorrió con bucles (los pocos recorridos se hicieron con while, que ya conocías). El for clásico se introduce ahora, en esta sección 6, como la herramienta natural para recorrer arrays. Tipos primitivos, var, String (con .equals(), .equalsIgnoreCase(), .length(), .trim(), .toLowerCase(), .matches(), .charAt()), text blocks, final para constantes y operador ternario (de UD1).


6.1 ¿De qué va esta sección? — El bucle versátil, en profundidad

En la sección 5 aprendiste los arrays unidimensionales como tipo compuesto: cómo se crean, cómo se inicializan y cómo se accede a sus elementos sueltos. Para los pocos recorridos que necesitaste, usaste while con un índice i y tuviste que acordarte del i++ al final del cuerpo. Es funcional pero verboso, y es muy fácil olvidar el i++ y provocar un bucle infinito.

En esta sección vas a conocer el for clásico: un bucle que agrupa inicialización + condición + actualización en una sola línea, lo que lo hace mucho más cómodo y seguro para recorrer arrays. Es el bucle natural para "pasar por todos los elementos de un array" (o de un String), y es la herramienta que vas a usar el 80 % de las veces que necesites iterar.

El for clásico no es más potente que el while (ambos son bucles con condición), pero es mucho más cómodo para el caso típico de "recorrer N elementos": te obliga a poner la inicialización, la condición y la actualización en la misma línea, así que no puedes olvidar ninguna de las tres. Y además tiene variantes que cubren casos especiales: recorrer al revés, saltar elementos, recorrer dos arrays a la vez, etc.

En esta sección vamos a introducir el for clásico desde cero y a profundizar en todas sus variantes. Cubriremos, en este orden:

  1. Anatomía detallada del for: las tres partes (inicialización, condición, actualización).
  2. El patrón estándar: for (int i = 0; i < arr.length; i++) — introducción al recorrido de arrays.
  3. Variante 1: decreciente — recorrer al revés.
  4. Variante 2: con saltos — i += 2, i *= 2, etc.
  5. Variante 3: múltiples variables — for (int i = 0, j = n-1; i < j; i++, j--).
  6. Variante 4: condición compleja — i < n && !encontrado.
  7. Variante 5: sin alguna de las tres partes — for (;;), for (; i < n; ), etc.
  8. for sobre Strings con charAt(i) — recorrer caracteres sin convertir a array.
  9. for sobre arrays de distintos tipos — int[], double[], String[], char[].
  10. for vs. while: criterios de elección.
  11. Trampas clásicas del for.
  12. Ejemplos resueltos paso a paso.

Analogía del contador de parking

El for clásico es como el contador automático de un parking: cada vez que entra un coche, sube una unidad; cuando llega al aforo máximo, se para. Tú configuras tres cosas: dónde empieza el contador (0), cuándo se para (< aforo), y cuánto sube en cada paso (+1). Pero también podrías configurarlo para que cuente atrás (de aforo a 0), que salte de 2 en 2 (si cada coche ocupa 2 plazas), o que cuente dos cosas a la vez (coches y motos). Esa flexibilidad es lo que hace el for clásico tan potente.

Vamos a empezar por despiezar el for parte por parte, para que veas por qué cada una existe y qué permite.


6.2 Anatomía detallada del for clásico

6.2.1 Las tres partes

La sintaxis general del for es:

1
2
3
for (inicialización; condición; actualización) {
    // cuerpo que se ejecuta en cada iteración
}

Cada una de las tres partes entre paréntesis tiene un papel:

Parte Qué hace Cuándo se ejecuta
Inicialización Prepara variables (normalmente el índice i). Una sola vez, antes de la primera comprobación.
Condición Expresión booleana evaluada antes de cada iteración. Si es true, se ejecuta el cuerpo; si es false, se sale. Antes de cada iteración (incluida la primera).
Actualización Modifica variables (normalmente i++). Después del cuerpo, antes de la siguiente comprobación.

6.2.2 Flujo de ejecución

flowchart TD
    Inicio([Inicio]) --> Init["Inicialización\n(p. ej. int i = 0)"]
    Init --> Cond{"¿Condición?\n(p. ej. i &lt; arr.length)"}
    Cond -->|true| Cuerpo["Cuerpo del bucle"]
    Cuerpo --> Update["Actualización\n(p. ej. i++)"]
    Update --> Cond
    Cond -->|false| Fin([Fin del bucle])

Detalles clave:

  1. La inicialización se ejecuta una sola vez, al principio. No se repite.
  2. La condición se evalúa antes de cada iteración, incluida la primera. Si ya es false al empezar, el cuerpo no se ejecuta ni una vez.
  3. La actualización se ejecuta después del cuerpo, antes de la siguiente comprobación. Es lo que hace que el bucle "avance".
  4. El orden es: init → cond → cuerpo → update → cond → cuerpo → update → ... → cond (false) → salir.

6.2.3 Las tres partes son opcionales, pero los puntos y comas no

Curiosamente, puedes dejar vacía cualquiera de las tres partes del for, pero los dos puntos y comas que las separan son obligatorios. Verás casos en la sección 6.7.

// Sin inicialización (la variable ya está declarada antes)
int i = 0;
for (; i < arr.length; i++) { ... }

// Sin actualización (se hace dentro del cuerpo)
for (int i = 0; i < arr.length; ) {
    // ... algo ...
    i++;   // la actualización va aquí, no en el for
}

// Sin condición (bucle "infinito" a propósito, sale con break — sección 7)
for (int i = 0; ; i++) {
    if (algo) break;
}

// Los tres vacíos: bucle infinito puro
for (;;) {
    if (algo) break;
}

Estas variantes son poco habituales (salvo el for (;;) que verás en bucles con break), pero conviene que las conozcas porque las vas a encontrar en código de otros.

6.2.4 Ámbito de la variable del for

La variable i declarada en la inicialización existe solo dentro del for (incluyendo la condición, la actualización y el cuerpo). Fuera del bucle, i no existe:

1
2
3
4
for (int i = 0; i < 5; i++) {
    IO.println(i);   // OK: i existe aquí
}
IO.println(i);   // ERROR: i no existe fuera del for

Si necesitas usar i después del bucle, decláralo fuera:

1
2
3
4
5
int i;
for (i = 0; i < 5; i++) {
    IO.println(i);
}
IO.println("Terminó en i = " + i);   // OK: i se declaró fuera

Pero esto es poco habitual: lo normal es declarar i dentro del for y olvidarte de él al terminar.

6.2.5 Varios índices en una sola inicialización

La inicialización puede declarar varias variables del mismo tipo, separadas por comas:

1
2
3
for (int i = 0, j = 10; i < j; i++, j--) {
    IO.println("i=" + i + ", j=" + j);
}

Esto lo verás en detalle en la sección 6.6 (múltiples variables). Por ahora quédate con que sí se puede, y que las variables tienen que ser del mismo tipo (no puedes declarar int i, double j en la misma inicialización).


6.3 El patrón estándar: recorrer un array por primera vez

Antes de ver las variantes, veamos el patrón estándar del for clásico, que es lo primero que necesitas aprender para recorrer un array. Compararemos con el while que ya conoces de la sección 5, para que veas por qué el for es más cómodo.

6.3.1 Recorrer un array con while (lo que ya sabes)

En la sección 5, cuando necesitaste recorrer un array (por ejemplo, para pedir 5 edades y guardarlas), usaste while con un índice i:

1
2
3
4
5
6
7
int[] numeros = {10, 20, 30, 40, 50};

int i = 0;
while (i < numeros.length) {
    IO.println(numeros[i]);
    i++;
}

Salida:

1
2
3
4
5
10
20
30
40
50

Esto funciona, pero requiere cuatro decisiones del programador, dispersas en tres líneas:

  1. int i = 0 declarado fuera del bucle.
  2. i < numeros.length como condición.
  3. i++ al final del cuerpo (¡fácil de olvidar! → bucle infinito).
  4. numeros[i] en el cuerpo para acceder al elemento.

6.3.2 El mismo recorrido con for clásico

1
2
3
4
5
int[] numeros = {10, 20, 30, 40, 50};

for (int i = 0; i < numeros.length; i++) {
    IO.println(numeros[i]);
}

Salida idéntica. Pero ahora, las tres primeras decisiones (int i = 0, i < numeros.length, i++) están agrupadas en la primera línea del for:

1
2
3
4
for (int i = 0; i < numeros.length; i++) {
//   ^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^ ^^^
//   inicializ.   condición            actualización
//   (una vez)    (antes de cada iter)  (después del cuerpo)

Esto es lo que hace el for más seguro: no puedes olvidar el i++, porque va en la cabecera, no en el cuerpo. Y no puedes confundir el orden de las partes, porque la sintaxis te obliga a ponerlas en el orden correcto.

6.3.3 Las cuatro decisiones del patrón estándar

  1. int i = 0: empezamos en 0 porque los índices de los arrays empiezan en 0 (lo viste en la sección 5).
  2. i < primos.length: usamos < (no <=) porque el último índice válido es length - 1 (también lo viste en la sección 5).
  3. i++: incrementamos de 1 en 1.
  4. primos[i]: accedemos al elemento actual usando el índice.

6.3.4 Recorrer un array de principio a fin con índice visible

1
2
3
4
5
int[] primos = {2, 3, 5, 7, 11};

for (int i = 0; i < primos.length; i++) {
    IO.println("Elemento " + i + " = " + primos[i]);
}

Salida:

1
2
3
4
5
Elemento 0 = 2
Elemento 1 = 3
Elemento 2 = 5
Elemento 3 = 7
Elemento 4 = 11

Aquí vemos el patrón más básico: recorrer un array imprimiendo cada elemento con su índice. Es la introducción al recorrido de arrays con for clásico.

6.3.5 Acumular (suma, producto, etc.)

El patrón más clásico: recorrer un array acumulando un valor.

1
2
3
4
5
6
7
int[] numeros = {10, 20, 30, 40, 50};

int suma = 0;
for (int i = 0; i < numeros.length; i++) {
    suma = suma + numeros[i];
}
IO.println("Suma: " + suma);   // 150

Detalles:

  • suma se declara fuera del bucle (si la declararas dentro, se reiniciaría en cada iteración).
  • suma = 0 porque sumamos; si multiplicáramos, empezaríamos en 1.
  • suma = suma + numeros[i] también se puede escribir suma += numeros[i] (asignación compuesta).

6.3.6 Buscar el máximo

1
2
3
4
5
6
7
8
9
int[] numeros = {5, 8, 3, 9, 2, 7};

int max = numeros[0];
for (int i = 1; i < numeros.length; i++) {   // empezamos en 1, no en 0
    if (numeros[i] > max) {
        max = numeros[i];
    }
}
IO.println("Máximo: " + max);   // 9

Aquí empezamos en i = 1 (no en 0) porque numeros[0] ya es el máximo inicial. Es una pequeña variante del patrón estándar.

6.3.7 Modificar elementos

El for clásico es la primera herramienta que ves que te permite modificar un array durante el recorrido. En la sección 5 solo accediste a elementos sueltos; aquí puedes recorrerlos todos y cambiarlos:

1
2
3
4
5
6
int[] numeros = {1, 2, 3, 4, 5};

for (int i = 0; i < numeros.length; i++) {
    numeros[i] = numeros[i] * 2;
}
// Ahora numeros = {2, 4, 6, 8, 10}

Aquí numeros[i] = numeros[i] * 2 es escritura sobre el elemento actual del array, no una copia. En la sección 7 verás que el for-each no puede hacer esto (la variable del for-each es una copia, no una referencia al elemento del array).

6.3.8 Imprimir con índice

1
2
3
4
5
String[] nombres = {"Ana", "Juan", "María"};

for (int i = 0; i < nombres.length; i++) {
    IO.println((i + 1) + ". " + nombres[i]);
}

Salida:

1
2
3
1. Ana
2. Juan
3. María

Fíjate en (i + 1): como los índices empiezan en 0, sumamos 1 al índice para mostrar "1, 2, 3" en vez de "0, 1, 2". Truco típico cuando presentas datos al usuario.


6.4 Variante 1: decreciente (recorrer al revés)

A veces necesitas recorrer un array del final al principio. Por ejemplo, para mostrar los elementos en orden inverso, o para某些 algoritmos de eliminación.

6.4.1 Sintaxis

1
2
3
for (int i = arr.length - 1; i >= 0; i--) {
    // cuerpo
}

Tres cambios respecto al patrón estándar:

  1. i = arr.length - 1: empezamos por el último índice válido.
  2. i >= 0: continuamos mientras i sea mayor o igual que 0 (cuando llega a -1, salimos).
  3. i--: decrementamos en cada paso (en vez de i++).

6.4.2 Ejemplo: imprimir al revés

1
2
3
4
5
int[] numeros = {10, 20, 30, 40, 50};

for (int i = numeros.length - 1; i >= 0; i--) {
    IO.println(numeros[i]);
}

Salida:

1
2
3
4
5
50
40
30
20
10

6.4.3 Ejemplo: invertir un array in-place

1
2
3
4
5
6
7
8
9
int[] numeros = {1, 2, 3, 4, 5};

// Invertir intercambiando elementos desde los extremos hacia el centro
for (int i = 0, j = numeros.length - 1; i < j; i++, j--) {
    int temp = numeros[i];
    numeros[i] = numeros[j];
    numeros[j] = temp;
}
// Ahora numeros = {5, 4, 3, 2, 1}

Este ejemplo usa múltiples variables (ver 6.6) y el patrón swap (intercambio con temp). Es un algoritmo clásico para invertir un array sin crear uno nuevo.

6.4.4 Trampa: i > 0 vs i >= 0

1
2
3
4
5
6
7
8
9
// BUG: se salta el primer elemento (i = 0)
for (int i = numeros.length - 1; i > 0; i--) {
    IO.println(numeros[i]);   // imprime del 4 al 1, NO el 0
}

// CORRECTO: i >= 0 para incluir el elemento 0
for (int i = numeros.length - 1; i >= 0; i--) {
    IO.println(numeros[i]);   // imprime del 4 al 0
}

Es la trampa simétrica a i < length vs i <= length. Aquí: si quieres incluir el índice 0, usa >= 0, no > 0.


6.5 Variante 2: con saltos

No tienes que ir de 1 en 1. Puedes saltar de k en k cambiando la actualización.

6.5.1 Saltar de 2 en 2

1
2
3
4
5
int[] numeros = {10, 20, 30, 40, 50, 60, 70};

for (int i = 0; i < numeros.length; i += 2) {
    IO.println(numeros[i]);   // imprime 10, 30, 50, 70
}

i += 2 es la actualización con salto. La condición i < numeros.length sigue siendo la misma. El cuerpo solo se ejecuta para i = 0, 2, 4, 6 (los pares).

6.5.2 Saltar de 3 en 3

1
2
3
for (int i = 0; i < numeros.length; i += 3) {
    IO.println(numeros[i]);   // imprime 10, 40, 70
}

6.5.3 Doble del índice (recorrido logarítmico)

1
2
3
for (int i = 1; i < numeros.length; i *= 2) {
    IO.println(numeros[i]);   // imprime numeros[1], numeros[2], numeros[4]
}

i *= 2 duplica i en cada paso. Útil para algoritmos de búsqueda binaria o recorrido exponencial (los verás en UD6 con estructuras avanzadas).

6.5.4 Casos de uso típicos

Salto Caso de uso
i += 2 Recorrer posiciones pares (o impares si empiezas en 1).
i += 3 Recorrer de 3 en 3 (p. ej. agrupar de tres en tres).
i *= 2 Recorrido exponencial (p. ej. búsqueda binaria).
i /= 2 Recorrido desde el final hacia la mitad (en algoritmos de división).

6.5.5 Trampa: la condición debe ser coherente con el salto

1
2
3
4
// BUG: si saltas de 2 en 2, podrías pasarte del length
for (int i = 0; i <= numeros.length; i += 2) {   // <= en vez de <
    numeros[i];   // ArrayIndexOutOfBoundsException cuando i == length (si length es par)
}

Con i += 2 (o cualquier salto > 1), i puede "saltarse" exactamente el valor length y caer en length + 1, lo cual sigue dando ArrayIndexOutOfBoundsException. Sigue usando <, no <=.


6.6 Variante 3: múltiples variables

La inicialización y la actualización pueden manejar varias variables a la vez.

6.6.1 Sintaxis

1
2
3
for (int i = 0, j = n - 1; i < j; i++, j--) {
    // cuerpo
}
  • Inicialización: int i = 0, j = n - 1 — declara dos variables int en una sola línea.
  • Condición: i < j — se cumple mientras no se crucen.
  • Actualización: i++, j-- — incrementa i y decrementa j a la vez.

6.6.2 Regla: variables del mismo tipo

Solo puedes declarar varias variables del mismo tipo en una sola inicialización. No puedes mezclar tipos:

1
2
3
4
5
// OK: dos int
for (int i = 0, j = 10; i < j; i++, j--) { ... }

// ERROR: no se puede mezclar int y double en la inicialización
for (int i = 0, double d = 0.0; ...; ...) { ... }

6.6.3 Ejemplo: invertir un array

Ya lo vimos en 6.4.3. Es el caso clásico de múltiples variables: i avanza desde el principio, j retrocede desde el final, se cruzan en el medio.

1
2
3
4
5
6
7
8
int[] numeros = {1, 2, 3, 4, 5};

for (int i = 0, j = numeros.length - 1; i < j; i++, j--) {
    int temp = numeros[i];
    numeros[i] = numeros[j];
    numeros[j] = temp;
}
// numeros = {5, 4, 3, 2, 1}

6.6.4 Ejemplo: recorrer dos arrays a la vez en paralelo

1
2
3
4
5
6
String[] nombres = {"Ana", "Juan", "María"};
int[] edades = {20, 25, 22};

for (int i = 0; i < nombres.length; i++) {
    IO.println(nombres[i] + " tiene " + edades[i] + " años");
}

Aquí solo declaramos i (un solo índice), pero usamos nombres[i] y edades[i] para acceder a ambos arrays en paralelo. Es un patrón muy común cuando tienes arrays paralelos (dos arrays cuyos elementos en la misma posición están relacionados).

Cuidado con los arrays paralelos

Los arrays paralelos son una mala práctica en POO: cuando veas clases en UD4, lo natural será tener una clase Alumno con nombre y edad juntos, en vez de dos arrays separados. Pero mientras no conozcas POO, los arrays paralelos con for clásico son la forma de resolver el problema.

6.6.5 Ejemplo: palíndromo

Comprobar si un array (o un String) es palíndromo (se lee igual al derecho y al revés) usando múltiples variables:

String palabra = "reconocer";
boolean esPalindromo = true;

for (int i = 0, j = palabra.length() - 1; i < j; i++, j--) {
    if (palabra.charAt(i) != palabra.charAt(j)) {
        esPalindromo = false;
        // Con break (sección 8) podríamos parar aquí
    }
}

IO.println("¿Es palíndromo? " + esPalindromo);   // true

Salida:

¿Es palíndromo? true

Aquí usamos i desde el principio y j desde el final, comparando charAt(i) con charAt(j). Si todos coinciden hasta cruzarse, es palíndromo.


6.7 Variante 4: condición compleja

La condición del for puede ser cualquier expresión booleana, no solo i < n.

6.7.1 Con un && para salir antes

int[] numeros = {5, 8, 3, 9, 2, 7};

boolean encontrado = false;
int buscar = 9;
int posicion = -1;

for (int i = 0; i < numeros.length && !encontrado; i++) {
    if (numeros[i] == buscar) {
        posicion = i;
        encontrado = true;
    }
}

Aquí la condición es i < numeros.length && !encontrado. El bucle sigue mientras no se acabe el array Y no se haya encontrado. En cuanto se encuentra (o se acaba el array), sale. Es una forma de "salir antes" sin usar break (que verás en la sección 8).

6.7.2 Con un || para condición alternativa

1
2
3
for (int i = 0; i < arr.length || i < 100; i++) {
    // Se ejecuta hasta recorrer el array O llegar a 100
}

Menos común, pero posible.

6.7.3 Con una llamada a método

1
2
3
for (int i = 0; i < arr.length && esValido(arr[i]); i++) {
    // Se ejecuta mientras no se acabe el array Y los elementos sean válidos
}

Aquí esValido(arr[i]) es una llamada a un método que devuelve boolean. La condición se evalúa en cada iteración, así que el método se llama en cada comprobación.


6.8 Variante 5: sin alguna de las tres partes

Como adelantamos en 6.2.3, puedes dejar vacía cualquiera de las tres partes.

6.8.1 Sin inicialización (variable ya declarada)

1
2
3
4
5
int i = 0;
for (; i < arr.length; i++) {
    // ...
}
// Aquí 'i' sigue siendo accesible (se declaró fuera)

Útil cuando necesitas usar i después del bucle.

6.8.2 Sin actualización (hecha en el cuerpo)

1
2
3
4
for (int i = 0; i < arr.length; ) {
    // ... algo ...
    i++;   // la actualización va dentro del cuerpo, no en el for
}

Útil cuando la actualización no es trivial (p. ej., depende de una condición).

6.8.3 Sin condición: for (;;) — bucle infinito

1
2
3
4
for (;;) {
    // ... algo ...
    if (condicionSalida) break;   // verás break en la sección 8
}

Es equivalente a while (true). Lo verás combinado con break en la sección 8, en el patrón "menú interactivo con while (true) + break". Por ahora no lo uses; prefiere while (true) que es más legible.

6.8.4 Sin inicialización ni actualización (equivalente a while)

int i = 0;
for (; i < arr.length; ) {
    // ...
    i++;
}
// Equivalente a:
int i = 0;
while (i < arr.length) {
    // ...
    i++;
}

Si te encuentras escribiendo esto, probablemente querías un while (ver 6.10).


6.9 for sobre Strings con charAt(i)

Ya viste en la sección 5 que puedes convertir un String en char[] con toCharArray() y luego acceder a sus caracteres sueltos por índice. Aquí verás cómo recorrerlos con for (cosa que no hicimos en la sección 5, donde solo accedimos a elementos sueltos). Además verás una alternativa que no crea un array nuevo: usar charAt(i) directamente sobre el String.

6.9.1 Sintaxis

1
2
3
4
5
6
String texto = "Hola";

for (int i = 0; i < texto.length(); i++) {
    char c = texto.charAt(i);
    // ... hacer algo con c
}

Diferencias con respecto a recorrer un array:

  • texto.length() (con paréntesis: es método), no texto.length (sin paréntesis: campo de array).
  • texto.charAt(i) para acceder al carácter, no texto[i] (los Strings no se pueden indexar directamente).

6.9.2 Ejemplo: imprimir cada carácter en una línea

1
2
3
4
5
String texto = "Hola";

for (int i = 0; i < texto.length(); i++) {
    IO.println(texto.charAt(i));
}

Salida:

1
2
3
4
H
o
l
a

6.9.3 Ejemplo: contar vocales con charAt

public class ContarVocalesCharAt {

    public static void main(String[] args) {

        IO.print("Escribe una palabra: ");
        String texto = IO.readln().trim();

        int vocales = 0;
        for (int i = 0; i < texto.length(); i++) {
            if (esVocal(texto.charAt(i))) {
                vocales++;
            }
        }
        IO.println("Vocales: " + vocales);
    }

    static boolean esVocal(char c) {
        char l = Character.toLowerCase(c);
        return l == 'a' || l == 'e' || l == 'i'
                || l == 'o' || l == 'u'
                || l == 'á' || l == 'é' || l == 'í'
                || l == 'ó' || l == 'ú';
    }
}

Salida con "Hola, mundo":

Vocales: 4

6.9.4 charAt vs toCharArray: ¿cuándo usar cada uno?

Criterio charAt(i) toCharArray() + for
¿Crea un array nuevo? No (más eficiente en memoria). Sí (crea un char[] nuevo).
¿Sintaxis? texto.charAt(i), un poco más verboso. arr[i], más limpio dentro del for.
¿Permite for-each (sección 7)? No, los String no se pueden recorrer con for-each directamente. Sí, una vez convertido a char[] puedes usar for-each sobre él.
¿Recomendado para... Recorridos simples, eficiencia en memoria. Casos donde quieres usar for-each o modificar el array (raro en Strings).

Regla del profesor:

Para recorrer un String con for clásico, usa charAt(i) (más eficiente, sin crear array). Si quieres usar for-each (sección 7), entonces sí convierte con toCharArray().

6.9.5 Trampa: índice fuera de rango en charAt

1
2
3
4
String texto = "hola";

char c = texto.charAt(4);   // ¡IndexOutOfBounds! (los índices válidos son 0-3)
char c = texto.charAt(-1);  // También IndexOutOfBounds

Atención: aunque el String lanza StringIndexOutOfBoundsException (no ArrayIndexOutOfBoundsException), el concepto es el mismo: índices fuera de rango. Verás cómo manejar esta excepción en la sección 9.

6.9.6 Recorrer un String al revés

1
2
3
4
5
6
String texto = "Hola";

for (int i = texto.length() - 1; i >= 0; i--) {
    IO.print(texto.charAt(i));
}
IO.println();   // "aloH"

Aquí combinamos dos cosas: la variante decreciente (6.4) y el acceso con charAt. Es el patrón estándar para invertir un String.


6.10 for vs. while: criterios de elección

El for clásico y el while pueden hacer lo mismo (ambos son bucles con condición), pero tienen casos de uso distintos. Elegir bien al principio te ahorra bugs y mejora la legibilidad.

6.10.1 Tabla comparativa

Criterio for while
¿Sabes cuántas iteraciones vas a hacer? Sí, usa for. No, usa while.
¿Necesitas un índice? Sí, for es natural. Posible, pero verboso (declarar antes, incrementar dentro).
¿La actualización es trivial (i++)? For, más limpio. While, más verboso.
¿La actualización es compleja (depende del cuerpo)? For con actualización vacía. While, más natural.
¿Bucle infinito con salida interna (con break)? for (;;) posible pero raro. while (true) es la forma idiomática.
¿Recorrer colección/array? Sí, for clásico. Posible, pero menos natural.
¿Mientras no cambie una condición externa? Posible con condición compleja. Sí, while es natural.

6.10.2 La regla de oro

"Si sabes cuántas iteraciones, usa for. Si depende de una condición que cambia, usa while."

Ejemplos:

1
2
3
4
5
6
7
8
// FOR: sé que son N iteraciones (recorrer un array de N elementos)
for (int i = 0; i < arr.length; i++) { ... }

// WHILE: no sé cuántas iteraciones (pedir dato hasta que sea válido)
while (!entradaValida) {
    entrada = IO.readln();
    entradaValida = entrada.matches("\\d+");
}

6.10.3 Regla secundaria

"Si necesitas un índice, for es más natural; si no, while suele ser más legible."

Ejemplos:

// FOR: necesito el índice para imprimir "1. ... 2. ... 3. ..."
for (int i = 0; i < nombres.length; i++) {
    IO.println((i + 1) + ". " + nombres[i]);
}

// WHILE: no necesito índice, solo espero a que el usuario escriba "salir"
while (true) {
    String op = IO.readln();
    if (op.equals("salir")) break;
    // ...
}

6.10.4 Cuándo uno se convierte en el otro

Cualquier for se puede reescribir como while y viceversa. Lo importante es elegir el que mejor comunica la intención:

// FOR equivalente a WHILE
for (int i = 0; i < arr.length; i++) { ... }
// Equivale a:
int i = 0;
while (i < arr.length) { ... ; i++; }

// WHILE equivalente a FOR
while (condicion) { ... }
// Equivale a:
for (; condicion; ) { ... }

Si te encuentras escribiendo un for con la inicialización y actualización vacías, eso es señal de que querías un while. Y viceversa: si tu while tiene un contador i que siempre se incrementa, eso es señal de que querías un for.

6.10.5 Diagrama de decisión

flowchart TD
    A["¿Vas a recorrer algo N veces?"] --> B{"¿Conoces N\nantes de empezar?"}
    B -->|Sí| C["**for clásico**"]
    B -->|No, depende de una condición| D["**while**"]
    C --> E{"¿Necesitas índice?"}
    E -->|Sí| F["for con i"]
    E -->|No, solo recorrer en orden| G["considera for-each (sección 7)"]
    D --> H["while con condición"]
    F --> Fin([Fin])
    G --> Fin
    H --> Fin

6.11 Trampas comunes del for clásico

Antes de pasar a los ejemplos, repasamos las trampas más típicas.

6.11.1 Trampa 1: < vs <= con length

Ya la vimos en la sección 5. La trampa nº 1 con arrays: usar <= en vez de <.

1
2
3
4
5
6
7
// BUG: llega a arr[arr.length] que no existe
for (int i = 0; i <= arr.length; i++) {
    arr[i];   // ArrayIndexOutOfBoundsException en la última
}

// CORRECTO
for (int i = 0; i < arr.length; i++) { ... }

6.11.2 Trampa 2: i > 0 vs i >= 0 al recorrer al revés

1
2
3
4
5
6
7
// BUG: se salta el índice 0
for (int i = arr.length - 1; i > 0; i--) {
    arr[i];   // imprime del length-1 al 1, NO el 0
}

// CORRECTO: incluye el 0
for (int i = arr.length - 1; i >= 0; i--) { ... }

6.11.3 Trampa 3: olvidar la actualización

// BUG: bucle infinito (i nunca cambia)
for (int i = 0; i < 10; ) {
    IO.println(i);   // imprime 0 infinitamente
}

// CORRECTO: añade i++ en la actualización
for (int i = 0; i < 10; i++) { ... }

// O dentro del cuerpo
for (int i = 0; i < 10; ) {
    IO.println(i);
    i++;
}

6.11.4 Trampa 4: la variable del for no existe fuera

1
2
3
4
5
6
7
for (int i = 0; i < 5; i++) { ... }
IO.println(i);   // ERROR: i no existe fuera del for

// Si necesitas i fuera, declárala fuera:
int i;
for (i = 0; i < 5; i++) { ... }
IO.println("Terminó en " + i);   // OK

6.11.5 Trampa 5: condiciones con && que cortan antes de tiempo

1
2
3
4
5
6
7
8
// BUG: si 'encontrado' se hace true en la última iteración,
// no llegamos a procesar el resto del array
for (int i = 0; i < arr.length && !encontrado; i++) {
    if (arr[i] == buscar) {
        encontrado = true;
        // si queríamos procesar el resto del array, ya no llegamos
    }
}

Esto no es un bug si tu intención era parar en cuanto encontraras. Pero asegúrate de que es eso lo que querías, no "procesar todos Y de paso buscar".

6.11.6 Trampa 6: confundir length y length() según el tipo

1
2
3
4
5
// Array: sin paréntesis
for (int i = 0; i < arr.length; i++) { ... }

// String: con paréntesis
for (int i = 0; i < texto.length(); i++) { ... }

Memoriza: array → length, String → length(). Ya lo vimos en la sección 5, pero conviene repetirlo porque es la fuente nº 1 de errores de compilación con bucles.

6.11.7 Trampa 7: múltiples variables de tipos distintos

1
2
3
4
5
6
// ERROR: no se pueden mezclar tipos en la inicialización
for (int i = 0, double d = 0.0; i < 10; i++) { ... }

// Si necesitas tipos distintos, declara uno fuera:
double d = 0.0;
for (int i = 0; i < 10; i++) { ... }

6.11.8 Resumen de trampas

Trampa Síntoma Solución
<= vs < con length ArrayIndexOutOfBoundsException. Usar <.
> 0 vs >= 0 al revés Se salta el índice 0. Usar >= 0.
Olvidar i++ Bucle infinito. Ponerlo en la actualización o en el cuerpo.
i no existe fuera Error de compilación. Declarar i antes del for si lo necesitas fuera.
&& que corta antes Procesamiento incompleto. Asegurar que es la intención (parar al encontrar).
length vs length() Error de compilación. Array → length, String → length().
Múltiples variables de tipos distintos Error de compilación. Declarar uno fuera.

6.12 Ejemplos resueltos paso a paso

Cinco ejemplos completos que integran todo lo aprendido.

6.12.1 Ejemplo 1: tabla de multiplicar (variantes estándar)

public class TablaMultiplicar {

    public static void main(String[] args) {

        final int N = 5;

        // Patrón estándar: de 1 a 10
        IO.println("=== Tabla del " + N + " ===");
        for (int i = 1; i <= 10; i++) {
            IO.println(N + " x " + i + " = " + (N * i));
        }
    }
}

Salida:

=== Tabla del 5 ===
5 x 1 = 5
5 x 2 = 10
5 x 3 = 15
5 x 4 = 20
5 x 5 = 25
5 x 6 = 30
5 x 7 = 35
5 x 8 = 40
5 x 9 = 45
5 x 10 = 50

Puntos clave:

  1. for (int i = 1; i <= 10; i++): empezamos en 1 (no en 0) porque las tablas empiezan en 1, y usamos <= (no <) porque queremos incluir el 10.
  2. Aquí no recorremos un array, solo iteramos del 1 al 10. Por eso la condición es <= 10 (no i < arr.length). Es una decisión distinta a la del patrón estándar de arrays.

6.12.2 Ejemplo 2: invertir un array in-place (múltiples variables)

import java.util.Arrays;

public class InvertirArray {

    public static void main(String[] args) {

        int[] numeros = {1, 2, 3, 4, 5};
        IO.println("Original: " + Arrays.toString(numeros));

        // Múltiples variables: i avanza, j retrocede
        for (int i = 0, j = numeros.length - 1; i < j; i++, j--) {
            int temp = numeros[i];
            numeros[i] = numeros[j];
            numeros[j] = temp;
        }

        IO.println("Invertido: " + Arrays.toString(numeros));
    }
}

Salida:

Original: [1, 2, 3, 4, 5]
Invertido: [5, 4, 3, 2, 1]

Puntos clave:

  1. Múltiples variables: int i = 0, j = numeros.length - 1 en la inicialización.
  2. Condición i < j: para cuando se cruzan (no hace falta procesar el centro dos veces).
  3. Actualización doble: i++, j-- (avanza uno, retrocede el otro).
  4. Swap con temp para no perder el valor al intercambiar.
  5. In-place: no crea un array nuevo, modifica el original.

6.12.3 Ejemplo 3: recorrer un String al revés (variante decreciente + charAt)

public class InvertirString {

    public static void main(String[] args) {

        IO.print("Escribe una palabra: ");
        String texto = IO.readln().trim();

        String invertido = "";
        for (int i = texto.length() - 1; i >= 0; i--) {
            invertido = invertido + texto.charAt(i);
        }

        IO.println("Invertido: " + invertido);
    }
}

Salida con "Hola":

Invertido: aloH

Puntos clave:

  1. texto.length() (con paréntesis, es método).
  2. Variante decreciente: empezamos en length() - 1, vamos hasta >= 0, decrementando con i--.
  3. texto.charAt(i) para acceder al carácter en la posición i sin crear un array nuevo.
  4. Concatenación invertido = invertido + ... para construir el String resultado. En UD2 verás StringBuilder para hacerlo más eficiente.

6.12.4 Ejemplo 4: recorrer dos arrays en paralelo

public class NombresEdades {

    public static void main(String[] args) {

        String[] nombres = {"Ana", "Juan", "María", "Pedro"};
        int[] edades = {20, 25, 22, 19};

        for (int i = 0; i < nombres.length; i++) {
            IO.println(nombres[i] + " tiene " + edades[i] + " años");
        }
    }
}

Salida:

1
2
3
4
Ana tiene 20 años
Juan tiene 25 años
María tiene 22 años
Pedro tiene 19 años

Puntos clave:

  1. Un solo índice i para ambos arrays. Usamos nombres[i] y edades[i] en cada iteración.
  2. Condición i < nombres.length: asumimos que ambos arrays tienen la misma longitud. Si no, esto es un bug (ver 6.12.5).
  3. Patrón de arrays paralelos: dos arrays cuyos elementos en la misma posición están relacionados. Cuando veas POO (UD4), lo natural será una clase Alumno con nombre y edad juntos.

6.12.5 Ejemplo 5: contar vocales con charAt y condición compleja

public class ContarVocalesHastaPunto {

    public static void main(String[] args) {

        IO.print("Escribe una frase (termina con punto): ");
        String texto = IO.readln();

        int vocales = 0;
        // Recorremos hasta el final o hasta encontrar un punto
        for (int i = 0; i < texto.length() && texto.charAt(i) != '.'; i++) {
            if (esVocal(texto.charAt(i))) {
                vocales++;
            }
        }

        IO.println("Vocales hasta el punto: " + vocales);
    }

    static boolean esVocal(char c) {
        char l = Character.toLowerCase(c);
        return l == 'a' || l == 'e' || l == 'i'
                || l == 'o' || l == 'u'
                || l == 'á' || l == 'é' || l == 'í'
                || l == 'ó' || l == 'ú';
    }
}

Salida con "Hola mundo. Adios.":

Vocales hasta el punto: 4

Puntos clave:

  1. Condición compleja: i < texto.length() && texto.charAt(i) != '.'. El bucle se detiene cuando se acaba el String o cuando encuentra un punto.
  2. charAt(i) dos veces en la condición y en el cuerpo: Java lo llama en cada acceso, pero es eficiente (no crea nada nuevo).
  3. Cuenta las vocales solo hasta el punto, ignorando el resto. Es el patrón "parar en condición".

6.13 Buenas prácticas con el for clásico

6.13.1 Las 10 reglas del for profesional

  1. Usa < con length, no <= (la trampa nº 1).
  2. Usa >= 0 al recorrer al revés, no > 0.
  3. No olvides la actualización (i++ o equivalente). Sin ella, bucle infinito.
  4. Declara i dentro del for salvo que la necesites fuera.
  5. El patrón estándar for (int i = 0; i < arr.length; i++) es el 80 % de los casos. Solo usa variantes cuando de verdad las necesites.
  6. Múltiples variables solo cuando es necesario (invertir, recorrer dos arrays). No abuses.
  7. charAt(i) para Strings con for clásico (más eficiente que toCharArray); reserva toCharArray para for-each (sección 7).
  8. length (array, sin paréntesis) vs length() (String, con paréntesis). Memorízalo.
  9. Si sabes cuántas iteraciones, usa for. Si no, while. Es la regla de oro.
  10. Comenta las variantes no estándar: si pones i += 2 o múltiples variables, un comentario breve ayuda al lector.

6.13.2 Cuándo refactorizar

Síntoma Refactoriza a
for con init y update vacíos. while (más natural para tu caso).
for (int i = 0; i < arr.length; i++) solo para recorrer sin tocar i. for-each (sección 7, más legible).
while (true) con contador i++ siempre. for (int i = 0; ...) (más natural).
for con condición && compleja. Considera break (sección 8) si la intención es "parar en cuanto".
Recorrer dos arrays paralelos. Cuando veas POO (UD4): clase con ambos campos.

6.13.3 Comentar el for

Los comentarios buenos en un for explican la intención del recorrido, no el bucle en sí:

// MAL: explica lo obvio
for (int i = 0; i < nums.length; i++) {   // recorre nums
    suma += nums[i];
}

// BIEN: explica la intención
// Sumamos las ventas del trimestre para calcular el bonus anual
int totalVentas = 0;
for (int i = 0; i < ventasTrimestre.length; i++) {
    totalVentas += ventasTrimestre[i];
}

// BIEN: explica una variante no estándar
// Invertimos el array in-place: i avanza, j retrocede, swap en el medio
for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
    int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp;
}

6.14 Resumen y mapa conceptual

6.14.1 Mapa conceptual

mindmap
  root((Sección 6 - for clásico))
    Anatomía
      Inicialización
      Condición
      Actualización
      Las 3 opcionales
      Ambito de i
    Patrón estándar
      i = 0; i length; i++
      Acumular
      Buscar máximo
      Modificar
    Variantes
      Decreciente al revés
      Con saltos i += 2
      Múltiples variables
      Condición compleja
      Sin alguna parte for (;;)
    Sobre Strings
      charAt i
      length con paréntesis
      Recorrer al revés
    Sobre arrays
      int double String char
      Recorrer modificar
    for vs while
      For si sabes N
      While si depende de condición
      for con índice
      while sin índice
    Trampas
      menor vs menor igual
      mayor vs mayor igual
      Olvidar i++
      i fuera de ámbito
      length vs length
      Tipos en múltiples variables

6.14.2 Las 12 ideas que no debes olvidar

  1. El for clásico tiene tres partes: inicialización, condición, actualización.
  2. La inicialización se ejecuta una sola vez; la condición se evalúa antes de cada iteración; la actualización se ejecuta después del cuerpo.
  3. El patrón estándar es for (int i = 0; i < arr.length; i++). Es el 80 % de los casos.
  4. Usa < con length, no <=. Es la trampa nº 1.
  5. Al recorrer al revés, usa i >= 0, no i > 0 (para incluir el índice 0).
  6. Puedes saltar con i += k: de 2 en 2, de 3 en 3, etc.
  7. Puedes usar múltiples variables: for (int i = 0, j = n-1; i < j; i++, j--). Tienen que ser del mismo tipo.
  8. La condición puede ser compleja: i < n && !encontrado, i < n && arr[i] != 0, etc.
  9. Las tres partes son opcionales, pero los dos ; son obligatorios. for (;;) es un bucle infinito.
  10. Para Strings, usa charAt(i) con for clásico (más eficiente que toCharArray). Reserva toCharArray para el for-each (sección 7).
  11. length (array, sin paréntesis) vs length() (String, con paréntesis). Memorízalo.
  12. for si sabes cuántas iteraciones; while si depende de una condición. Es la regla de oro para elegir entre ambos.

6.14.3 Glosario rápido

Término Significado
for clásico Bucle con inicialización, condición y actualización en una sola línea.
Inicialización Primera parte del for: prepara variables (normalmente int i = 0).
Condición Segunda parte: expresión booleana evaluada antes de cada iteración.
Actualización Tercera parte: modifica variables después del cuerpo (normalmente i++).
Patrón estándar for (int i = 0; i < arr.length; i++) — el caso más común.
Variante decreciente for (int i = n - 1; i >= 0; i--) — recorrer al revés.
Variante con saltos for (int i = 0; i < n; i += k) — saltar de k en k.
Múltiples variables for (int i = 0, j = n - 1; ...; i++, j--) — dos índices en un solo for.
for (;;) Bucle infinito equivalente a while (true). Suele combinarse con break.
charAt(i) Método de String que devuelve el carácter en la posición i.
length Campo de array (sin paréntesis): número de elementos.
length() Método de String (con paréntesis): número de caracteres.
Arrays paralelos Dos o más arrays cuyos elementos en la misma posición están relacionados. Mala práctica en POO (mejor una clase con varios campos).
Swap Intercambio de dos valores usando una variable temp auxiliar.
StringIndexOutOfBoundsException Excepción que lanza charAt(i) cuando i está fuera de rango.

6.15 Actividades propuestas

Cinco actividades graduadas. Hazlas en orden. Las soluciones se publicarán en Aules.

6.15.1 Actividad 1 — Tabla de multiplicar completa

Objetivo: practicar el patrón estándar del for (sin array, solo iteración numérica).

Enunciado: Escribe un programa que pida al usuario un número N (entre 1 y 10) y muestre la tabla de multiplicar de N, del 1 al 10, con este formato:

1
2
3
4
5
Tabla del 7
7 x 1 = 7
7 x 2 = 14
...
7 x 10 = 70

Requisitos:

  • Valida que N esté entre 1 y 10 con matches.
  • Usa for (int i = 1; i <= 10; i++). Fíjate que es <= 10, no < 10 (no es un array, es una iteración numérica).

Entrega: archivo TablaMultiplicar.java en el paquete jams.programacion.ud3.

Criterios evaluados: CE 3.2, CE 3.5, CE 3.7.

6.15.2 Actividad 2 — Invertir un array in-place

Objetivo: practicar múltiples variables y el patrón swap.

Enunciado: Dado un array de 8 enteros:

int[] datos = {3, 7, 1, 9, 4, 6, 2, 8};

Imprime el array original, inviértelo in-place (sin crear un array nuevo) usando la técnica de i que avanza y j que retrocede con swap, y muestra el resultado. Ambas impresiones con Arrays.toString.

Requisitos:

  • Usa for (int i = 0, j = datos.length - 1; i < j; i++, j--).
  • Realiza el swap dentro del cuerpo con una variable temp.
  • Importa java.util.Arrays.

Entrega: archivo InvertirArray.java en el paquete jams.programacion.ud3.

Criterios evaluados: CE 3.2, CE 3.5, CE 3.7.

6.15.3 Actividad 3 — Invertir un String

Objetivo: practicar la variante decreciente con charAt sobre Strings.

Enunciado: Pide al usuario una palabra y muestra su inverso (caracteres en orden inverso). Por ejemplo, "Hola" → "aloH".

Requisitos:

  • Usa for (int i = texto.length() - 1; i >= 0; i--).
  • Usa texto.charAt(i) para acceder a cada carácter.
  • Construye el resultado concatenando con +.
  • No uses toCharArray() (esa es la alternativa que verás con for-each en la sección 7).

Entrega: archivo InvertirString.java en el paquete jams.programacion.ud3.

Criterios evaluados: CE 3.2, CE 3.5, CE 3.7.

6.15.4 Actividad 4 — Comprobar palíndromo

Objetivo: practicar múltiples variables sobre Strings con charAt.

Enunciado: Pide al usuario una palabra y di si es palíndromo (se lee igual al derecho y al revés). Ignora mayúsculas con toLowerCase antes de comprobar. Ejemplos:

  • "reconocer" → sí es palíndromo.
  • "Hola" → no es palíndromo.
  • "Ana" → sí es palíndromo (ignorando mayúsculas).
  • "Radar" → sí es palíndromo (ignorando mayúsculas).

Requisitos:

  • Normaliza la entrada con .trim().toLowerCase().
  • Usa for (int i = 0, j = texto.length() - 1; i < j; i++, j--).
  • Compara texto.charAt(i) != texto.charAt(j). Si encuentras alguna diferencia, no es palíndromo.
  • Muestra "Es palíndromo" o "No es palíndromo".

Entrega: archivo Palindromo.java en el paquete jams.programacion.ud3.

Criterios evaluados: CE 3.2, CE 3.5, CE 3.7.

6.15.5 Actividad 5 — Cuestionario de repaso

Responde por escrito:

  1. ¿Cuáles son las tres partes del for clásico y cuándo se ejecuta cada una?
  2. Escribe el patrón estándar para recorrer un array de principio a fin.
  3. ¿Por qué se usa < con length y no <=?
  4. Escribe la variante decreciente para recorrer un array al revés.
  5. ¿Por qué en la variante decreciente se usa i >= 0 y no i > 0?
  6. Escribe un for que recorra posiciones pares de un array.
  7. Escribe un for con múltiples variables para invertir un array.
  8. ¿Puedes declarar varias variables de tipos distintos en la inicialización del for? ¿Por qué?
  9. ¿Qué es for (;;) y para qué sirve?
  10. ¿Cómo recorres los caracteres de un String con for clásico sin crear un array nuevo?
  11. ¿Cuál es la diferencia entre length y length()? ¿Cuándo se usa cada uno?
  12. ¿Cuándo eliges for y cuándo while? Pon un ejemplo de cada caso.

Entrega: archivo cuestionario_seccion6.md con tus respuestas.

Criterios evaluados: CE 3.2, CE 3.7.


6.16 Lo que NO hemos visto (y dónde verlo)

Esta sección te ha enseñado el for clásico en profundidad: desde el patrón estándar (que introduce el recorrido de arrays, que no se había visto en la sección 5) hasta todas sus variantes sobre arrays y Strings. Hay varias cosas relacionadas que se reservan para secciones/unidades posteriores:

Concepto ¿Por qué no aquí? ¿Dónde se ve?
for-each (recorrido sin índice) Bucle distinto al for clásico. Sección 7 de UD3.
break y continue Sentencias de salto de bucle. Sección 8 de UD3.
break etiquetado Para salir de bucles anidados. Sección 8 de UD3.
Bucles anidados (for dentro de for) Combinación de bucles. Sección 8 de UD3.
Matrices bidimensionales int[][] Arrays de arrays. Sección 8 de UD3.
try-catch para manejar ArrayIndexOutOfBoundsException y StringIndexOutOfBoundsException Manejo de excepciones. Sección 9 de UD3.
StringBuilder para concatenación eficiente en bucles Clase del API Java. UD2 (POO con la API de Java).
Streams API como alternativa a bucles Forma declarativa de procesar colecciones. UD6.
Iterable<T> y colecciones (List, Set) Tipos avanzados de datos. UD6.

6.17 Lo que viene en la sección 7

Con esta sección ya dominas el for clásico en todas sus variantes sobre arrays y Strings. Pero hay un caso muy común en el que el for clásico es más verboso de lo necesario: cuando solo quieres recorrer todos los elementos en orden, sin necesidad de índice.

En la sección 7 verás el for-each (también llamado enhanced for), un bucle más simple y seguro para recorrer arrays sin índice:

1
2
3
4
5
6
7
8
9
// for clásico: más verboso
for (int i = 0; i < numeros.length; i++) {
    IO.println(numeros[i]);
}

// for-each: más limpio
for (int n : numeros) {
    IO.println(n);
}

Aprenderás:

  • Sintaxis del for-each: for (Tipo elemento : array) { ... }.
  • Cómo recorre todos los elementos sin índice.
  • Cuándo usar for-each y cuándo for clásico (la regla: for-each lee, for clásico escribe).
  • La limitación del for-each: no modifica el array (la variable es una copia).
  • Recorrer caracteres de un String con toCharArray() + for-each.

Cuando termines la sección 7, tendrás las dos herramientas de recorrido completas: for clásico (con índice, para casos que lo necesitan) y for-each (sin índice, para recorrido simple). Después, en la sección 8 cerrarás el bloque de iteración con bucles anidados, matrices bidimensionales y sentencias de salto (break, continue, return).


Cierre del profesor. Llegar hasta aquí es mérito. Ya dominas el for clásico en todas sus variantes: patrón estándar, decreciente, con saltos, múltiples variables, condición compleja, sobre Strings con charAt. Eso es el 80 % de lo que necesitas para recorrer arrays y strings en cualquier programa. La regla más importante que te llevas es < no <= con length: el 90 % de los bugs con for vienen de usar <=. La segunda es for si sabes cuántas iteraciones, while si no: elegir bien entre ambos hace tu código más legible. Nos vemos en la sección 7, donde verás el for-each como forma más simple y segura de recorrer arrays cuando no necesitas el índice. Es la última pieza del bloque de iteración simple antes de los bucles anidados.