La sintaxis de Java para el control de flujo hereda la claridad de C, pero introduce salvaguardas críticas para la robustez del software. En esta materia, nos enfocamos en el uso preciso de estas estructuras para construir algoritmos eficientes y seguros.
El control de flujo se refiere a las instrucciones que determinan el orden en que se ejecutan las sentencias de un programa. Sin estructuras de control, un programa ejecutaría sus instrucciones de forma secuencial, de arriba hacia abajo, sin posibilidad de tomar decisiones o repetir acciones. Las estructuras de control permiten:
Decisiones: Ejecutar diferentes bloques de código según condiciones (
if,switch)Iteración: Repetir bloques de código múltiples veces (
for,while,do-while)Transferencia: Alterar el flujo dentro de estructuras (
break,continue,return)
Lógica Booleana y Cortocircuito¶
Una de las diferencias fundamentales con C es que en Java el tipo boolean no es un entero. Por lo tanto, estructuras como if (1) son errores de compilación.
En C, cualquier valor distinto de cero se interpreta como verdadero y cero como falso. Esto permite escribir código como if (x) donde x es un entero, lo cual puede ser fuente de errores sutiles. Java elimina esta ambigüedad: las condiciones deben ser expresiones booleanas.
// En C esto es válido (pero peligroso):
// if (x = 5) { ... } // Asigna 5 a x, evalúa como verdadero
// En Java esto NO compila (error de tipos):
int x = 5;
// if (x) { } // Error: incompatible types: int cannot be converted to boolean
if (x != 0) { } // Correcto: expresión booleana explícitaDiferencia entre C y Java en condiciones
Operadores Relacionales¶
Los operadores relacionales comparan dos valores y devuelven un resultado boolean (true o false). Son idénticos a los de C:
| Operador | Significado | Ejemplo | Resultado si x = 5 |
|---|---|---|---|
== | Igual a | x == 5 | true |
!= | Distinto de | x != 5 | false |
< | Menor que | x < 5 | false |
> | Mayor que | x > 5 | false |
<= | Menor o igual que | x <= 5 | true |
>= | Mayor o igual que | x >= 5 | true |
Operadores Lógicos¶
Los operadores lógicos combinan expresiones booleanas para formar condiciones más complejas:
| Operador | Significado | Ejemplo | Descripción |
|---|---|---|---|
&& | AND lógico (con cortocircuito) | a && b | true solo si ambos son true |
|| | OR lógico (con cortocircuito) | a || b | true si al menos uno es true |
! | NOT lógico (negación) | !a | Invierte el valor booleano |
Estos operadores son idénticos a los de C, pero solo funcionan con operandos booleanos (no con enteros).
boolean esMayor = true;
boolean tieneDNI = false;
// AND: ambas condiciones deben ser verdaderas
boolean puedeVotar = esMayor && tieneDNI; // false
// OR: al menos una condición debe ser verdadera
boolean puedeEntrar = esMayor || tieneDNI; // true
// NOT: invierte el valor
boolean esmenor = !esMayor; // falseUso de operadores lógicos
Tabla de Verdad de los Operadores Lógicos¶
a | b | a && b | a || b | !a |
|---|---|---|---|---|
true | true | true | true | false |
true | false | false | true | false |
false | true | false | true | true |
false | false | false | false | true |
Evaluación en Cortocircuito (Short-circuit Evaluation)¶
Los operadores && (AND) y || (OR) realizan una evaluación perezosa o en cortocircuito. Esto significa que Java deja de evaluar la expresión tan pronto como puede determinar el resultado final:
a && b: Siaesfalse,bno se evalúa porque el resultado es necesariamentefalse(en un AND, si uno es falso, todo es falso).a || b: Siaestrue,bno se evalúa porque el resultado es necesariamentetrue(en un OR, si uno es verdadero, todo es verdadero).
Esta característica no es solo una optimización de rendimiento; es una herramienta fundamental para escribir código seguro.
Figure 1:Diagrama de evaluación en cortocircuito: cuando la primera condición determina el resultado, la segunda no se evalúa.
Operadores Lógicos Sin Cortocircuito¶
Java también proporciona los operadores & y | (un solo símbolo) que evalúan ambos operandos siempre, incluso si el resultado ya está determinado. Estos se usan raramente y principalmente cuando los operandos tienen efectos secundarios que deben ejecutarse.
int x = 0;
boolean resultado1 = (false && (++x > 0)); // x sigue siendo 0
boolean resultado2 = (false & (++x > 0)); // x ahora es 1 (se evaluó ++x)Diferencia entre & y &&
Estructuras Condicionales¶
Las estructuras condicionales permiten que un programa tome decisiones durante su ejecución. En lugar de seguir un camino lineal, el programa puede elegir entre diferentes bloques de código según el valor de una condición.
En términos de flujo de programa, las estructuras condicionales crean bifurcaciones: puntos donde el camino de ejecución se divide en dos o más alternativas.
La Sentencia if¶
La sentencia if es la estructura condicional más básica. Ejecuta un bloque de código solo si una condición es verdadera.
if (condicion) {
// código que se ejecuta si condicion es true
}
// La ejecución continúa aquí, independientemente de la condiciónEstructura básica del if
Anatomía del if:
La palabra reservada
ifUna condición entre paréntesis que debe evaluar a
booleanUn bloque de código entre llaves que se ejecuta si la condición es
true
La condición debe ser una expresión que evalúe a boolean. A diferencia de C, no se puede usar un entero directamente.
int temperatura = 35;
if (temperatura > 30) {
System.out.println("Hace calor");
}
// Si temperatura es 25, no se imprime nada y el programa continúaEjemplo de if simple
La Sentencia if-else¶
Permite ejecutar un bloque alternativo cuando la condición es falsa. Esto crea una bifurcación completa: el programa siempre ejecutará exactamente uno de los dos bloques.
if (condicion) {
// código si condicion es true (rama verdadera)
} else {
// código si condicion es false (rama falsa)
}Estructura if-else
int edad = 17;
if (edad >= 18) {
System.out.println("Es mayor de edad");
} else {
System.out.println("Es menor de edad");
}
// Siempre se imprime exactamente uno de los dos mensajesEjemplo de if-else
La Sentencia if-else if-else¶
Cuando se necesitan evaluar múltiples condiciones mutuamente excluyentes, se encadenan sentencias else if. Esta estructura crea una cadena de decisiones donde solo se ejecuta el primer bloque cuya condición sea verdadera.
if (condicion1) {
// código si condicion1 es true
} else if (condicion2) {
// código si condicion1 es false y condicion2 es true
} else if (condicion3) {
// código si condicion1 y condicion2 son false y condicion3 es true
} else {
// código si ninguna condición anterior es true (opcional pero recomendado)
}Estructura if-else if-else
Características importantes:
Las condiciones se evalúan en orden, de arriba hacia abajo
La ejecución entra solo al primer bloque cuya condición es verdadera
Una vez que se ejecuta un bloque, se salta al código después de toda la estructura
El
elsefinal es opcional pero recomendado para manejar casos no previstos
int nota = 75;
String clasificacion;
if (nota >= 90) {
clasificacion = "Sobresaliente";
} else if (nota >= 80) {
clasificacion = "Muy bueno";
} else if (nota >= 70) {
clasificacion = "Bueno";
} else if (nota >= 60) {
clasificacion = "Regular";
} else {
clasificacion = "Insuficiente";
}
// Si nota es 75, solo se ejecuta clasificacion = "Bueno"
// Las condiciones >= 60 nunca se evalúan porque ya se encontró una verdaderaEjemplo de clasificación de notas
Condicionales Anidados¶
Es posible colocar estructuras if dentro de otras estructuras if. Esto se llama anidamiento y permite expresar condiciones más complejas.
int edad = 25;
boolean tieneLicencia = true;
if (edad >= 18) {
System.out.println("Es mayor de edad");
if (tieneLicencia) {
System.out.println("Puede conducir");
} else {
System.out.println("Necesita obtener licencia");
}
} else {
System.out.println("Es menor de edad, no puede conducir");
}Ejemplo de if anidado
El Operador Ternario ? :¶
El operador ternario (también llamado operador condicional) es una forma compacta de expresar una selección entre dos valores. Es el único operador de Java que toma tres operandos.
resultado = condicion ? valorSiTrue : valorSiFalse;Sintaxis del operador ternario
Funcionamiento:
Se evalúa la
condicionSi es
true, el resultado esvalorSiTrueSi es
false, el resultado esvalorSiFalse
int edad = 20;
String estado = (edad >= 18) ? "Mayor" : "Menor";
// Equivale a:
String estado2;
if (edad >= 18) {
estado2 = "Mayor";
} else {
estado2 = "Menor";
}Ejemplo del operador ternario
El operador ternario es una expresión (devuelve un valor), no una sentencia. Por eso puede usarse en cualquier lugar donde se espere un valor:
// En una asignación
int maximo = (a > b) ? a : b;
// En una llamada a método
System.out.println("El valor es " + ((x > 0) ? "positivo" : "no positivo"));
// En un return
return (lista.isEmpty()) ? valorPorDefecto : lista.get(0);Usos del operador ternario como expresión
La Sentencia switch¶
El switch permite seleccionar entre múltiples alternativas basándose en el valor de una expresión. Es útil cuando se compara una variable contra varios valores constantes, especialmente cuando hay muchas alternativas.
Diferencia conceptual con if-else if:
if-else if: evalúa condiciones booleanas (pueden ser cualquier expresión)switch: compara un valor contra constantes conocidas
El switch es más legible cuando se tienen muchas comparaciones de igualdad contra el mismo valor.
Switch Clásico (Sentencia)¶
La versión clásica del switch requiere break para evitar el “fall-through” (caída en cascada hacia el siguiente caso).
switch (expresion) {
case valor1:
// código para valor1
break;
case valor2:
// código para valor2
break;
case valor3:
case valor4:
// código para valor3 O valor4 (casos agrupados)
break;
default:
// código si ningún caso coincide
break;
}Estructura del switch clásico
Anatomía del switch:
expresion: El valor a evaluar (debe ser de tipo compatible)case valor:: Etiqueta que marca el código a ejecutar siexpresion == valorbreak: Termina la ejecución del switch y salta al código posteriordefault: Caso opcional que se ejecuta si ningúncasecoincide
int diaSemana = 3;
String nombreDia;
switch (diaSemana) {
case 1:
nombreDia = "Lunes";
break;
case 2:
nombreDia = "Martes";
break;
case 3:
nombreDia = "Miércoles";
break;
case 4:
nombreDia = "Jueves";
break;
case 5:
nombreDia = "Viernes";
break;
case 6:
case 7:
nombreDia = "Fin de semana"; // Casos 6 y 7 comparten el mismo código
break;
default:
nombreDia = "Día inválido";
break;
}Ejemplo de switch con días de la semana
Tipos de datos permitidos en el switch clásico:
Tipos enteros:
byte,short,int,char(nolong)String: desde Java 7 se pueden usar cadenasTipos enumerados (
enum): se estudian más adelante
String comando = "salir";
switch (comando) {
case "iniciar":
System.out.println("Iniciando...");
break;
case "pausar":
System.out.println("Pausando...");
break;
case "salir":
System.out.println("Saliendo...");
break;
default:
System.out.println("Comando no reconocido");
break;
}Switch con String
Switch Moderno (Expresión, Java 14+)¶
El switch moderno utiliza la flecha -> para eliminar el riesgo de caída accidental y puede devolver un valor directamente. Esta versión es más segura y concisa.
Diferencias con el switch clásico:
No requiere
break(no hay fall-through)Puede usarse como expresión (devuelve un valor)
Múltiples valores en un solo
caseseparados por comasSintaxis más concisa con flechas
->
int diaSemana = 3;
String nombreDia = switch (diaSemana) {
case 1 -> "Lunes";
case 2 -> "Martes";
case 3 -> "Miércoles";
case 4 -> "Jueves";
case 5 -> "Viernes";
case 6, 7 -> "Fin de semana"; // Múltiples valores en un caso
default -> "Día inválido";
}; // Nota el punto y coma: es una expresión que termina en asignaciónSwitch expresión con sintaxis de flecha
Cuando se necesita ejecutar varias sentencias en un caso, se usa un bloque con yield para retornar el valor:
String descripcion = switch (estado) {
case ACTIVO -> "Sistema funcionando";
case PENDIENTE -> {
System.out.println("Procesando pendiente...");
yield "Esperando confirmación"; // yield retorna el valor del bloque
}
case ERROR -> {
registrarError();
notificarAdministrador();
yield "Sistema en error";
}
default -> "Estado desconocido";
};Switch con bloques múltiples líneas y yield
Estructuras de Repetición: Lazos¶
En Java, utilizamos el término lazos para referirnos a los bucles o ciclos. Los lazos permiten ejecutar un bloque de código múltiples veces sin tener que escribirlo repetidamente.
Los lazos son fundamentales para:
Procesar colecciones de datos (arreglos, listas)
Repetir acciones hasta que se cumpla una condición
Implementar algoritmos iterativos
Generar secuencias de valores
Cada tipo de lazo tiene una semántica específica según el punto de evaluación de la condición:
Lazo
for: cuando se conoce la cantidad de iteracionesLazo
while: cuando se repite mientras una condición sea verdadera (evaluación al inicio)Lazo
do-while: cuando se necesita al menos una ejecución (evaluación al final)
Figure 2:Comparación del flujo de ejecución entre for, while y do-while. Observá cuándo se evalúa la condición en cada caso.
El Lazo for¶
El lazo for es ideal cuando se conoce de antemano la cantidad de iteraciones. Consta de tres partes separadas por punto y coma: inicialización, condición y actualización.
for (inicializacion; condicion; actualizacion) {
// código que se repite mientras condicion sea true
}Estructura del lazo for
Las tres partes del for:
Inicialización: Se ejecuta una sola vez, antes de la primera iteración. Generalmente declara e inicializa la variable de control.
Condición: Se evalúa antes de cada iteración. Si es
true, se ejecuta el cuerpo; si esfalse, el lazo termina.Actualización: Se ejecuta después de cada iteración, antes de volver a evaluar la condición. Generalmente modifica la variable de control.
La ejecución sigue este orden:
Se ejecuta la inicialización (una sola vez)
Se evalúa la condición
Si es
true, se ejecuta el cuerpo del lazoSe ejecuta la actualización
Se vuelve al paso 2
for (int i = 1; i <= 5; i = i + 1) {
System.out.println(i);
}
// Imprime: 1, 2, 3, 4, 5
// Traza de ejecución:
// i=1: condición 1<=5 es true, imprime 1, actualiza i=2
// i=2: condición 2<=5 es true, imprime 2, actualiza i=3
// i=3: condición 3<=5 es true, imprime 3, actualiza i=4
// i=4: condición 4<=5 es true, imprime 4, actualiza i=5
// i=5: condición 5<=5 es true, imprime 5, actualiza i=6
// i=6: condición 6<=5 es false, termina el lazoEjemplo de for que imprime números del 1 al 5
for (int i = 10; i >= 0; i = i - 1) {
System.out.println(i);
}
// Imprime: 10, 9, 8, ..., 1, 0Ejemplo de for con conteo descendente
// Imprimir números pares del 0 al 20
for (int i = 0; i <= 20; i = i + 2) {
System.out.println(i);
}
// Imprime: 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20Ejemplo de for con incremento diferente
Partes Opcionales del for¶
Todas las partes del for son opcionales (aunque se deben mantener los punto y coma):
// Variable ya inicializada afuera
int i = 0;
for (; i < 10; i = i + 1) {
System.out.println(i);
}
// Actualización dentro del cuerpo
for (int j = 0; j < 10; ) {
System.out.println(j);
j = j + 1;
}
// Lazo infinito (usar con cuidado)
// for (;;) {
// // Se ejecuta indefinidamente
// }Variantes del for
El Lazo while¶
El lazo while evalúa la condición antes de ejecutar el cuerpo. Si la condición es falsa desde el inicio, el cuerpo nunca se ejecuta (cero iteraciones).
while (condicion) {
// código que se repite mientras condicion sea true
}Estructura del lazo while
Características del while:
La condición se evalúa antes de cada iteración
Si la condición es inicialmente
false, el cuerpo no se ejecuta nuncaNo tiene inicialización ni actualización integradas (se deben hacer por separado)
Es ideal cuando no se sabe cuántas iteraciones serán necesarias
int suma = 0;
int numero = 1;
while (suma < 100) {
suma = suma + numero;
numero = numero + 1;
}
System.out.println("Suma final: " + suma);
System.out.println("Último número sumado: " + (numero - 1));
// Traza: suma=0, agrega 1 (suma=1), agrega 2 (suma=3), agrega 3 (suma=6)...
// Continúa hasta que suma >= 100Ejemplo de while para sumar números hasta llegar a un límite
int x = 10;
while (x < 5) { // Condición es false desde el inicio
System.out.println(x); // Nunca se ejecuta
x = x + 1;
}
System.out.println("Lazo terminado"); // Se imprime directamenteEjemplo de while que no ejecuta ninguna iteración
Figure 3:Patrón recomendado: búsqueda con bandera booleana en lugar de break. La bandera encontrado controla la terminación anticipada del lazo.
boolean encontrado = false; // Bandera: indica si encontramos el valor
int indice = 0;
// El lazo continúa mientras no hayamos encontrado Y queden elementos
while (indice < cantidad && !encontrado) {
if (elementos[indice] == valorBuscado) {
encontrado = true; // Encontramos el valor, el lazo terminará
// NO incrementamos indice para conservar la posición encontrada
} else {
indice = indice + 1; // Avanzar solo si no encontramos
}
}
// Después del lazo, verificamos qué pasó
if (encontrado) {
System.out.println("Encontrado en posición: " + indice);
} else {
System.out.println("No encontrado");
}Búsqueda con bandera (patrón recomendado)
Este patrón tiene varias ventajas:
El lazo tiene una única condición de salida clara
El estado final es predecible:
encontradoindica el resultado,indiceindica la posiciónEs fácil de depurar y entender
El Lazo do-while¶
El lazo do-while evalúa la condición después de ejecutar el cuerpo. Esto garantiza que el cuerpo se ejecuta al menos una vez, independientemente del valor de la condición.
do {
// código que se ejecuta al menos una vez
} while (condicion); // Nota: termina con punto y comaEstructura del lazo do-while
Características del do-while:
El cuerpo se ejecuta antes de evaluar la condición
Siempre hay al menos una iteración (mínimo garantizado: 1)
La condición se evalúa al final de cada iteración
Si la condición es
falsedespués de la primera ejecución, el lazo termina
int opcion;
do {
System.out.println("Menú:");
System.out.println("1. Opción A");
System.out.println("2. Opción B");
System.out.println("0. Salir");
System.out.print("Seleccione: ");
opcion = scanner.nextInt();
} while (opcion != 0);
// El menú se muestra al menos una vez antes de verificar si el usuario quiere salirEjemplo de do-while para validar entrada
int numero;
do {
System.out.print("Ingrese un número entre 1 y 10: ");
numero = scanner.nextInt();
if (numero < 1 || numero > 10) {
System.out.println("Valor fuera de rango. Intente nuevamente.");
}
} while (numero < 1 || numero > 10);
System.out.println("Número válido ingresado: " + numero);Ejemplo de do-while para validar rango
Diferencia entre while y do-while¶
int x = 100;
// Con while: no se ejecuta ninguna vez
while (x < 10) {
System.out.println("while: " + x);
x = x + 1;
}
// Con do-while: se ejecuta exactamente una vez
do {
System.out.println("do-while: " + x); // Imprime "do-while: 100"
x = x + 1;
} while (x < 10);Comparación con condición inicialmente falsa
Comparación de Lazos¶
| Lazo | Evaluación de Condición | Ejecución Mínima | Uso Típico | Estructura Equivalente en C |
|---|---|---|---|---|
for | Antes de cada iteración | 0 veces | Cantidad de iteraciones conocida | Idéntica |
while | Antes de cada iteración | 0 veces | Cantidad de iteraciones desconocida | Idéntica |
do-while | Después de cada iteración | 1 vez | Se requiere al menos una ejecución | Idéntica |
Guía para elegir el lazo correcto:
// FOR: cuando conocés la cantidad de iteraciones
// "Hacer algo N veces" o "recorrer de A a B"
for (int i = 0; i < 10; i = i + 1) {
// Exactamente 10 iteraciones (0 a 9)
}
// WHILE: cuando no sabés cuántas iteraciones, pero podría ser cero
// "Mientras haya datos" o "hasta que se cumpla X"
while (hayMasDatos()) {
procesarSiguiente();
}
// DO-WHILE: cuando necesitás al menos una iteración
// "Hacer al menos una vez, repetir si es necesario"
do {
pedirDato();
} while (!datoValido());Cuándo usar cada tipo de lazo
Equivalencia entre for y while¶
Todo lazo for puede reescribirse como while y viceversa. La elección entre uno u otro es principalmente una cuestión de claridad y convención:
Usá
forcuando la estructura tiene una inicialización, condición y actualización clarasUsá
whilecuando solo tenés una condición de continuación
for (int i = 0; i < 10; i = i + 1) {
System.out.println(i);
}Lazo for
int i = 0; // Inicialización (antes del lazo)
while (i < 10) { // Condición
System.out.println(i);
i = i + 1; // Actualización (al final del cuerpo)
}Equivalente con while
Lazos Anidados¶
Es posible colocar un lazo dentro de otro. El lazo interno se ejecuta completamente por cada iteración del lazo externo. Esto es útil para trabajar con estructuras bidimensionales (matrices) o generar combinaciones.
for (int fila = 1; fila <= 5; fila = fila + 1) {
for (int columna = 1; columna <= 5; columna = columna + 1) {
int producto = fila * columna;
System.out.print(producto + "\t"); // \t es tabulador
}
System.out.println(); // Nueva línea después de cada fila
}
// Salida:
// 1 2 3 4 5
// 2 4 6 8 10
// 3 6 9 12 15
// 4 8 12 16 20
// 5 10 15 20 25Ejemplo de lazos anidados (tabla de multiplicar)
Análisis de la ejecución:
El lazo externo (
fila) itera 5 vecesPor cada iteración del lazo externo, el lazo interno (
columna) itera 5 vecesTotal de iteraciones del cuerpo interno: 5 × 5 = 25 veces
for (int i = 1; i <= 3; i = i + 1) {
System.out.println("Lazo externo: i = " + i);
for (int j = 1; j <= 2; j = j + 1) {
System.out.println(" Lazo interno: j = " + j);
}
}
// Salida:
// Lazo externo: i = 1
// Lazo interno: j = 1
// Lazo interno: j = 2
// Lazo externo: i = 2
// Lazo interno: j = 1
// Lazo interno: j = 2
// Lazo externo: i = 3
// Lazo interno: j = 1
// Lazo interno: j = 2Traza de lazos anidados
Lazos Infinitos y Cómo Evitarlos¶
Un lazo infinito es un lazo cuya condición nunca se vuelve falsa, causando que el programa se ejecute indefinidamente (hasta que se lo detenga externamente o se agote algún recurso).
// Error 1: Condición siempre verdadera
while (true) {
System.out.println("Infinito!");
}
// Error 2: Variable de control no modificada
int i = 0;
while (i < 10) {
System.out.println(i);
// Falta: i = i + 1;
}
// Error 3: Actualización en dirección incorrecta
for (int j = 0; j < 10; j = j - 1) { // j decrece, nunca llega a 10
System.out.println(j);
}
// Error 4: Condición que no puede volverse falsa
int k = 1;
while (k != 10) { // k solo toma valores impares
System.out.println(k);
k = k + 2; // k: 1, 3, 5, 7, 9, 11, 13, ... nunca es 10
}Ejemplos de lazos infinitos (errores comunes)
Cómo evitar lazos infinitos:
Verificar que la variable de control se modifique en cada iteración
Verificar que la modificación acerque la condición a ser falsa
Usar condiciones con
<o>en lugar de!=cuando sea posibleEvitar punto flotante como variables de control
Sentencias de Control de Flujo: break y continue¶
Java proporciona las sentencias break y continue para alterar el flujo normal de los lazos. Estas sentencias permiten salir anticipadamente de un lazo o saltar a la siguiente iteración.
La Sentencia break¶
La sentencia break termina inmediatamente el lazo más interno que la contiene. La ejecución continúa en la primera sentencia después del lazo.
// Búsqueda con break - NO USAR en este curso
for (int i = 0; i < 100; i = i + 1) {
if (valores[i] == buscado) {
System.out.println("Encontrado en: " + i);
break; // Sale del lazo inmediatamente
}
}
// Equivalente con bandera (USAR en este curso)
boolean encontrado = false;
int i = 0;
while (i < 100 && !encontrado) {
if (valores[i] == buscado) {
encontrado = true;
} else {
i = i + 1;
}
}
if (encontrado) {
System.out.println("Encontrado en: " + i);
}Ejemplo de break (uso general, NO permitido en este curso)
La Sentencia continue¶
La sentencia continue salta a la siguiente iteración del lazo, omitiendo el resto del código en la iteración actual. En un for, ejecuta la actualización antes de verificar la condición.
// Imprimir solo impares con continue - NO USAR en este curso
for (int i = 0; i < 10; i = i + 1) {
if (i % 2 == 0) {
continue; // Salta los números pares
}
System.out.println(i); // Solo imprime impares
}
// Equivalente sin continue (USAR en este curso)
for (int i = 0; i < 10; i = i + 1) {
if (i % 2 != 0) { // Condición invertida
System.out.println(i);
}
}Ejemplo de continue (uso general, NO permitido en este curso)
Uso Permitido de break: en switch¶
El único lugar donde break está permitido en este curso es dentro de sentencias switch, donde es necesario para evitar el fall-through:
switch (opcion) {
case 1:
hacerOpcion1();
break; // Permitido y necesario
case 2:
hacerOpcion2();
break; // Permitido y necesario
default:
hacerDefault();
break;
}break permitido en switch
Comparativa de Seguridad con C¶
Java hereda la sintaxis de control de flujo de C pero añade verificaciones que previenen errores comunes:
1. Asignación en Condiciones¶
En C, if (x = 5) es un error común que asigna 5 a x y evalúa a verdadero (porque 5 es distinto de cero). En Java, esto falla en compilación (a menos que x sea boolean), previniendo errores lógicos sutiles.
int x = 0;
// En C esto compila y siempre es verdadero (asigna 5 a x)
// En Java esto NO compila:
// if (x = 5) { } // Error: incompatible types: int cannot be converted to boolean
// Forma correcta:
if (x == 5) { } // ComparaciónProtección contra asignación accidental
2. Inicialización Obligatoria¶
Java exige que las variables locales estén inicializadas antes de ser usadas en cualquier estructura de control. El compilador analiza todos los caminos posibles.
int resultado;
if (condicion) {
resultado = 10;
}
// Error de compilación: variable resultado might not have been initialized
// System.out.println(resultado);
// Correcto: inicializar en todas las ramas
if (condicion) {
resultado = 10;
} else {
resultado = 0;
}
System.out.println(resultado); // OKVerificación de inicialización
3. Tipo Booleano Estricto¶
Las condiciones deben ser expresiones boolean. No se puede usar un entero, referencia a objeto, o cualquier otro tipo directamente como condición.
int cantidad = 5;
String texto = "hola";
// Estos NO compilan en Java (sí en C):
// if (cantidad) { } // Error: int no es boolean
// while (texto) { } // Error: String no es boolean
// Forma correcta:
if (cantidad != 0) { } // Comparación explícita
while (texto != null) { } // Comparación explícitaCondiciones estrictamente booleanas
4. Alcance de Variables en Lazos¶
En Java moderno, declarar la variable de control en el for la limita al ámbito del lazo, evitando conflictos de nombres y uso accidental posterior.
for (int i = 0; i < 10; i = i + 1) {
System.out.println(i);
}
// i no existe aquí - evita errores
for (int i = 0; i < 5; i = i + 1) {
// Esta i es diferente, sin conflicto
System.out.println(i);
}Alcance limitado de variables de control
Estas diferencias hacen que Java sea más seguro que C para programación a gran escala, aunque la sintaxis sea visualmente similar.
Ejercicios de Nivel Universitario¶
Gracias al **cortocircuito** del operador `&&`, si `x` es 0, la primera condición `(x != 0)` evalúa a `false`. En ese momento, Java detiene la evaluación de la expresión completa porque ya sabe que el resultado será `false` (en un AND, si uno es falso, todo es falso). Por lo tanto, la segunda parte `(y / x > 1)` **nunca se ejecuta** cuando `x` es 0, evitando así la división por cero. Este patrón es muy común para proteger operaciones que podrían fallar: ```java // Proteger división if (divisor != 0 && dividendo / divisor > limite) { ... } // Proteger acceso a arreglo if (indice >= 0 && indice < arr.length && arr[indice] == valor) { ... } // Proteger referencia nula if (objeto != null && objeto.metodo()) { ... }
```{exercise}
:label: ej-for-while
Reescribí el siguiente lazo `for` como un lazo `while` equivalente:
`for (int i = 10; i > 0; i = i - 2) { System.out.println(i); }`El switch es más legible cuando hay muchas comparaciones de igualdad contra el mismo valor.
````{exercise}
:label: ej-lazos-anidados
Escribí un programa que imprima el siguiente patrón usando lazos anidados:
**
Referencias Bibliográficas¶
Schildt, H. (2022). Java: A Beginner’s Guide (9na ed.). McGraw Hill. (Capítulo 3: Program Control Statements).
Liang, Y. D. (2017). Introduction to Java Programming and Data Structures (11va ed.). Pearson.
Bloch, J. (2018). Effective Java (3ra ed.). Addison-Wesley Professional.
Oracle Corporation. (2023). The Java Language Specification. Control Flow.
- {ref}`regla-0x5001` - Estilo de llaves y bloques en estructuras de control.
- {ref}`regla-0xE001` - Comparación de tipos primitivos vs objetos.