Módulo 05: Estructuras condicionales
Objetivos del módulo
- Construir expresiones booleanas correctas con operadores relacionales y lógicos
- Tomar decisiones con
if,if-elsey la escaleraif-else-if - Anidar condicionales y saber cuándo conviene simplificarlos
- Entender qué es un bloque y el ámbito de las variables declaradas dentro de él
- Usar el operador ternario
? :en los casos en que mejora la legibilidad - Dominar el
switchclásico (break, fallthrough,default) y las expresionesswitchde Java 14+ (->,yield, exhaustividad) - Usar
switchconint,charyString - Comparar cadenas con
equalsy entender por qué==no sirve - Reconocer y evitar los errores típicos de los condicionales
- Traducir cada estructura entre diagrama de flujo, pseudocódigo y Java
1. Programas que toman decisiones
Hasta ahora todos tus programas eran secuenciales: las instrucciones se ejecutaban una detrás de otra, de arriba abajo, siempre todas y siempre en el mismo orden. Pero casi ningún problema real es así. Piensa en cosas que haces cada día:
- Si llueve, cojo el paraguas.
- Si el semáforo está en verde, cruzo; si no, espero.
- Según el día de la semana, voy a clase, a trabajar o descanso.
📘 Concepto: Una estructura condicional (o de selección) permite que el programa elija qué instrucciones ejecutar en función de una condición, es decir, de una expresión que solo puede ser verdadera (
true) o falsa (false).
En el módulo 02 viste las tres estructuras de control de la programación estructurada: secuencia, selección e iteración. Con ellas se puede escribir cualquier algoritmo (teorema de Böhm-Jacopini). En este módulo traducimos la selección a Java y en el siguiente, la iteración.
| Estructura | Pseudocódigo | Java |
|---|---|---|
| Selección simple | Si ... Entonces ... FinSi | if (...) { ... } |
| Selección doble | Si ... Entonces ... SiNo ... FinSi | if (...) { ... } else { ... } |
| Selección múltiple | Si ... SiNo Si ... / Segun ... Hacer | if-else-if / switch |
Para cada estructura verás tres representaciones del mismo algoritmo: el diagrama de flujo, el pseudocódigo y el código Java. Así podrás pasar de una a otra con soltura, que es justo lo que se pide en los exámenes de primer curso.
2. Expresiones booleanas
Toda decisión depende de una condición, y en Java una condición es siempre una expresión de tipo boolean. No vale un número (como en C o JavaScript): if (1) es un error de compilación en Java.
2.1. Operadores relacionales
Comparan dos valores y devuelven true o false:
| Operador | Significado | Ejemplo | Resultado si x = 7 |
|---|---|---|---|
== | igual a | x == 7 | true |
!= | distinto de | x != 7 | false |
< | menor que | x < 5 | false |
<= | menor o igual que | x <= 7 | true |
> | mayor que | x > 0 | true |
>= | mayor o igual que | x >= 10 | false |
⚠️ Importante:
=es asignación («guarda este valor») y==es comparación («¿son iguales?»). Confundirlos es el error número uno de los principiantes. Lo verás en la sección de errores típicos.
2.2. Operadores lógicos
Combinan condiciones:
| Operador | Nombre | Es true cuando… | Ejemplo |
|---|---|---|---|
&& | Y lógico (AND) | las dos partes son true | edad >= 18 && tieneCarne |
\|\| | O lógico (OR) | al menos una parte es true | edad < 26 \|\| edad >= 65 |
! | NO lógico (NOT) | la expresión es false | !tieneCarne |
Tabla de verdad completa:
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 |
2.3. Evaluación en cortocircuito
Java evalúa && y || de izquierda a derecha y se detiene en cuanto conoce el resultado:
- En
a && b, siaesfalse, el resultado ya esfalseybno se evalúa. - En
a || b, siaestrue, el resultado ya estrueybno se evalúa.
Esto no es un detalle académico: sirve para proteger la segunda condición. En divisor != 0 && dividendo / divisor > 2, si el divisor es cero nunca se llega a dividir, así que no se produce la excepción ArithmeticException.
💡 Consejo: Existen también
&y|aplicados aboolean, que evalúan siempre las dos partes. No los uses en condiciones: casi nunca es lo que quieres. Utilízalos solo en operaciones con bits, que no son objeto de este curso.
2.4. Precedencia
De mayor a menor prioridad: ! → aritméticos (*, /, %, +, -) → relacionales (<, <=, >, >=) → igualdad (==, !=) → && → || → ternario ? : → asignación =.
Por eso a || b && c significa a || (b && c). Aunque conozcas la tabla, usa paréntesis cuando mezcles && y ||: el lector lo agradecerá.
2.5. Leyes de De Morgan
Sirven para negar condiciones compuestas sin equivocarte:
!(a && b)equivale a!a || !b!(a || b)equivale a!a && !b
Ejemplo: «no es cierto que la edad esté entre 18 y 65» → !(edad >= 18 && edad <= 65) → edad < 18 || edad > 65.
💻 Ejemplo: Todos estos operadores en acción:
public class Booleanas {
public static void main(String[] args) {
int edad = 20;
boolean tieneCarne = false;
// Relacionales: el resultado siempre es true o false
System.out.println("edad >= 18 -> " + (edad >= 18));
System.out.println("edad != 20 -> " + (edad != 20));
// Lógicos
System.out.println("conducir -> " + (edad >= 18 && tieneCarne));
System.out.println("descuento -> " + (edad < 26 || edad >= 65));
System.out.println("!tieneCarne -> " + !tieneCarne);
System.out.println("entre 18 y 65 -> " + (edad >= 18 && edad <= 65));
// Cortocircuito: como divisor es 0, la división NO llega a hacerse
int dividendo = 10, divisor = 0;
System.out.println("cortocircuito -> " + (divisor != 0 && dividendo / divisor > 2));
// De Morgan: !(a && b) es lo mismo que !a || !b
boolean a = true, b = false;
System.out.println("!(a && b) -> " + !(a && b));
System.out.println("!a || !b -> " + (!a || !b));
}
}
Salida:
edad >= 18 -> true
edad != 20 -> false
conducir -> false
descuento -> true
!tieneCarne -> true
entre 18 y 65 -> true
cortocircuito -> false
!(a && b) -> true
!a || !b -> true
⚠️ Importante: En matemáticas escribes
18 <= edad <= 65, pero en Java eso no compila (18 <= edadda unboolean, y no se puede comparar unbooleancon65). Siempre se escribe con dos comparaciones unidas por&&:edad >= 18 && edad <= 65.
💡 Consejo: Guarda las condiciones complicadas en variables
booleancon nombre:boolean puedeConducir = edad >= 18 && tieneCarne;. Después,if (puedeConducir)se lee como una frase. Y nunca escribasif (puedeConducir == true): es redundante.
3. Condicional simple: if
El if ejecuta un bloque de instrucciones solo si la condición es verdadera. Si es falsa, el bloque se salta y el programa continúa después de él.
Figura 1. Diagrama de flujo del condicional simple.
Pseudocódigo:
Algoritmo MayorDeEdad
Escribir "Introduce tu edad: "
Leer edad
Si edad >= 18 Entonces
Escribir "Eres mayor de edad."
Escribir "Ya puedes votar."
FinSi
Escribir "Fin del programa."
FinAlgoritmo
Sintaxis en Java: if (condición) { instrucciones }.
- La condición va siempre entre paréntesis.
- Las instrucciones van entre llaves
{ }, que forman un bloque. - No se pone
;después deif (condición).
import java.util.Scanner;
public class MayorDeEdad {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Introduce tu edad: ");
int edad = sc.nextInt();
if (edad >= 18) {
System.out.println("Eres mayor de edad.");
System.out.println("Ya puedes votar.");
}
System.out.println("Fin del programa.");
}
}
Dos ejecuciones:
Introduce tu edad: 20
Eres mayor de edad.
Ya puedes votar.
Fin del programa.
Introduce tu edad: 15
Fin del programa.
Con 15 años la condición es falsa: las dos líneas del bloque no se ejecutan, pero «Fin del programa.» sí, porque está fuera del if.
💡 Consejo: Si el bloque tiene una sola instrucción, Java permite omitir las llaves (
if (edad >= 18) System.out.println("...");). No lo hagas: es fuente de errores (sección 13) y casi todas las guías de estilo profesionales, como la de Google, exigen llaves siempre.
4. Condicional doble: if-else
Cuando hay que hacer una cosa u otra, se añade else («si no»). Se ejecuta exactamente uno de los dos bloques, nunca los dos y nunca ninguno.
Figura 2. Diagrama de flujo del condicional doble.
Algoritmo ParImpar
Escribir "Introduce un número entero: "
Leer n
Si n MOD 2 = 0 Entonces
Escribir n, " es par."
SiNo
Escribir n, " es impar."
FinSi
FinAlgoritmo
import java.util.Scanner;
public class ParImpar {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Introduce un número entero: ");
int n = sc.nextInt();
if (n % 2 == 0) {
System.out.println(n + " es par.");
} else {
System.out.println(n + " es impar.");
}
}
}
Introduce un número entero: 7
7 es impar.
📘 Concepto:
n % 2es el resto de dividirnentre 2 (operador módulo del módulo 03). Si es 0, el número es par. Ojo: con negativos,-7 % 2vale-1, no1; por eso se compara con== 0y no con== 1para detectar impares.
5. Condicional múltiple: la escalera if-else-if
Cuando hay más de dos caminos posibles, se encadenan varios else if. Java evalúa las condiciones en orden, de arriba abajo, ejecuta el bloque de la primera que sea verdadera y se salta todas las demás. El else final (opcional) recoge el caso en que ninguna se cumple.
Figura 3. Diagrama de flujo de la escalera if-else-if.
Algoritmo Calificacion
Escribir "Introduce la nota (0-10): "
Leer nota
Si nota < 0 O nota > 10 Entonces
texto <- "Nota no válida"
SiNo Si nota < 5 Entonces
texto <- "Insuficiente"
SiNo Si nota < 6 Entonces
texto <- "Suficiente"
SiNo Si nota < 7 Entonces
texto <- "Bien"
SiNo Si nota < 9 Entonces
texto <- "Notable"
SiNo
texto <- "Sobresaliente"
FinSi
Escribir "Calificación: ", texto
FinAlgoritmo
import java.util.Scanner;
public class Calificacion {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Introduce la nota (0-10): ");
double nota = sc.nextDouble();
String texto;
if (nota < 0 || nota > 10) {
texto = "Nota no válida";
} else if (nota < 5) {
texto = "Insuficiente";
} else if (nota < 6) {
texto = "Suficiente";
} else if (nota < 7) {
texto = "Bien";
} else if (nota < 9) {
texto = "Notable";
} else {
texto = "Sobresaliente";
}
System.out.println("Calificación: " + texto);
}
}
Dos ejecuciones, una con una nota válida y otra fuera de rango:
Introduce la nota (0-10): 7.5
Calificación: Notable
Introduce la nota (0-10): 11
Calificación: Nota no válida
Fíjate en que la segunda condición es solo nota < 5, no nota >= 0 && nota < 5: si llegamos a ella es porque la primera fue falsa, así que ya sabemos que la nota está entre 0 y 10. Cada escalón aprovecha lo que descartaron los anteriores.
⚠️ Importante: Los resultados de este curso se generaron con la configuración regional inglesa, por eso escribimos
7.5yprintfmuestra127.50. Si tu sistema está en español,Scannerespera coma decimal (7,5) y lanzaráInputMismatchExceptionsi escribes un punto;printfmostrará127,50. Lo viste en el módulo 04: si quieres usar siempre el punto, crea el lector connew Scanner(System.in).useLocale(java.util.Locale.US).
5.1. El orden de las condiciones importa
Como solo se ejecuta la primera rama verdadera, un orden incorrecto produce resultados absurdos:
double nota = 9.5;
if (nota >= 5) { // ¡MAL! Es cierta y "se come" a las demás
System.out.println("Aprobado"); // se imprime "Aprobado"
} else if (nota >= 7) {
System.out.println("Notable"); // nunca se ejecuta
} else if (nota >= 9) {
System.out.println("Sobresaliente"); // nunca se ejecuta
}
Con un 9.5 debería salir «Sobresaliente», pero nota >= 5 ya es cierta y las demás ramas nunca se evalúan. Hay dos soluciones: ordenar de más restrictiva a menos (>= 9, luego >= 7, luego >= 5) o hacerlo como en Calificacion, comparando con < de menor a mayor.
5.2. Escalera frente a varios if independientes
No es lo mismo. Con x = 20:
// Escalera: como máximo se ejecuta UNA rama -> solo imprime "positivo"
if (x > 0) {
System.out.println("positivo");
} else if (x > 10) {
System.out.println("mayor que 10");
}
// if independientes: se evalúan TODOS -> imprime las dos líneas
if (x > 0) { System.out.println("positivo"); }
if (x > 10) { System.out.println("mayor que 10"); }
Usa la escalera cuando los casos sean excluyentes (una nota solo tiene una calificación) y varios if cuando sean independientes (un usuario puede ser a la vez mayor de edad y socio).
6. Condicionales anidados
Un condicional anidado es un if dentro de otro if (o dentro de un else). Se usa cuando una decisión solo tiene sentido después de haber tomado otra.
Ejemplo: una tienda hace un 15 % de descuento a los socios que gastan 100 € o más, un 5 % a los socios que gastan menos y también un 5 % a los no socios que gastan 100 € o más.
Figura 4. Condicionales anidados: cada rama del primer if contiene otro if.
Algoritmo Descuento
Leer importe, socio
Si socio = 1 Entonces
Si importe >= 100 Entonces
descuento <- 0.15
SiNo
descuento <- 0.05
FinSi
SiNo
Si importe >= 100 Entonces
descuento <- 0.05
SiNo
descuento <- 0
FinSi
FinSi
total <- importe - importe * descuento
Escribir descuento, total
FinAlgoritmo
import java.util.Scanner;
public class Descuento {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Importe de la compra (€): ");
double importe = sc.nextDouble();
System.out.print("¿Eres socio? (1 = sí, 0 = no): ");
int socio = sc.nextInt();
double descuento;
if (socio == 1) {
// Condicional anidado: solo se evalúa si es socio
if (importe >= 100) {
descuento = 0.15;
} else {
descuento = 0.05;
}
} else {
if (importe >= 100) {
descuento = 0.05;
} else {
descuento = 0;
}
}
double total = importe - importe * descuento;
System.out.printf("Descuento aplicado: %.0f %%%n", descuento * 100);
System.out.printf("Total a pagar: %.2f €%n", total);
}
}
Importe de la compra (€): 150
¿Eres socio? (1 = sí, 0 = no): 1
Descuento aplicado: 15 %
Total a pagar: 127.50 €
💡 Consejo: En
printf,%%escribe un símbolo%literal. Por eso el formato es"%.0f %%%n".
6.1. Cuándo aplanar un anidamiento
Dos if anidados sin else equivalen a uno solo con &&: if (edad >= 18) { if (tieneCarne) { ... } } es lo mismo que if (edad >= 18 && tieneCarne) { ... }, que se lee mejor.
Más de tres niveles de anidamiento hacen el código difícil de leer (el famoso «código en flecha»). Cuando te pase, plantéate combinar condiciones, usar una escalera o, a partir del módulo 07, sacar parte del código a un método.
6.2. ¿A qué if pertenece el else?
Un else siempre pertenece al if más cercano que no tenga ya su else, independientemente de cómo esté sangrado el código:
if (a > 0)
if (b > 0)
System.out.println("los dos positivos");
else // ¡pertenece a if (b > 0)!
System.out.println("a no es positivo");
Si a = 5 y b = -1, se imprime «a no es positivo», que es falso. Es el problema del else colgante (dangling else) y desaparece en cuanto pones llaves: con if (a > 0) { if (b > 0) { ... } } else { ... } queda claro que el else pertenece al if externo.
7. Bloques y ámbito de las variables
📘 Concepto: Un bloque es un grupo de instrucciones entre llaves
{ }. El ámbito (scope) de una variable es la zona del código donde existe y se puede usar: desde su declaración hasta la llave que cierra el bloque en el que se declaró.
Consecuencias prácticas:
- Una variable declarada dentro de un
ifdesaparece al salir de él. - Una variable declarada fuera (antes) del
ifse puede leer y modificar dentro, y conserva el valor al salir. - No puedes declarar dentro de un bloque una variable con el mismo nombre que otra local que siga existiendo fuera (Java lo prohíbe para evitar confusiones).
public class Ambito {
public static void main(String[] args) {
int puntos = 120; // visible en todo main
String nivel = "básico"; // declarada FUERA del if
if (puntos >= 100) {
int extra = puntos - 100; // solo existe dentro de este bloque
nivel = "avanzado"; // modifica la variable de fuera
System.out.println("Puntos extra: " + extra);
}
System.out.println("Nivel: " + nivel);
// System.out.println(extra); // ERROR: extra ya no existe aquí
}
}
Puntos extra: 20
Nivel: avanzado
Si quitas el comentario de la última línea, el compilador protesta:
public class AmbitoError {
public static void main(String[] args) {
int puntos = 120;
if (puntos >= 100) {
int extra = puntos - 100;
}
System.out.println(extra);
}
}
AmbitoError.java:7: error: cannot find symbol
System.out.println(extra);
^
symbol: variable extra
location: class AmbitoError
1 error
💡 Consejo: Cuando necesites un valor calculado dentro de un
ifdespués delif, declara la variable antes y asígnale el valor en cada rama, como hacemos contextoenCalificacion. El compilador comprueba que la variable tenga valor en todos los caminos posibles; si te olvidas de una rama, verás el errorvariable texto might not have been initialized.
8. El operador ternario ? :
Es una forma compacta de un if-else que devuelve un valor:
variable = condición ? valorSiTrue : valorSiFalse;
Se llama ternario porque tiene tres operandos. Es una expresión (produce un valor), no una sentencia: puedes usarlo dentro de una asignación, de un println o de una concatenación.
public class Ternario {
public static void main(String[] args) {
int a = 8, b = 13;
// Equivale a: if (a > b) { mayor = a; } else { mayor = b; }
int mayor = (a > b) ? a : b;
System.out.println("Mayor: " + mayor);
// Muy útil para elegir un texto
int manzanas = 1;
System.out.println("Tengo " + manzanas + (manzanas == 1 ? " manzana" : " manzanas"));
manzanas = 3;
System.out.println("Tengo " + manzanas + (manzanas == 1 ? " manzana" : " manzanas"));
double nota = 4.9;
String resultado = nota >= 5 ? "APTO" : "NO APTO";
System.out.println("Resultado: " + resultado);
}
}
Mayor: 13
Tengo 1 manzana
Tengo 3 manzanas
Resultado: NO APTO
⚠️ Importante: Usa el ternario solo para elecciones simples entre dos valores. Si anidas ternarios (
a ? b : c ? d : e) o pones acciones complicadas dentro, el código se vuelve ilegible: usa unif-elsenormal. Los dos valores deben ser de tipos compatibles.
9. El switch clásico
Cuando la decisión consiste en comparar una misma variable con una lista de valores concretos, una escalera if-else-if funciona, pero queda larga. Para eso existe switch. En pseudocódigo es la estructura Segun:
Algoritmo DiaSemana
Escribir "Número de día (1-7): "
Leer dia
Segun dia Hacer
1: Escribir "Lunes"
2: Escribir "Martes"
3: Escribir "Miércoles"
4: Escribir "Jueves"
5: Escribir "Viernes"
6: Escribir "Sábado"
7: Escribir "Domingo"
De Otro Modo: Escribir "Día no válido"
FinSegun
FinAlgoritmo
En Java, la forma clásica (la que existe desde Java 1.0 y encontrarás en mucho código y en libros) es:
import java.util.Scanner;
public class DiaSemana {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Número de día (1-7): ");
int dia = sc.nextInt();
switch (dia) {
case 1:
System.out.println("Lunes");
break;
case 2:
System.out.println("Martes");
break;
case 3:
System.out.println("Miércoles");
break;
case 4:
System.out.println("Jueves");
break;
case 5:
System.out.println("Viernes");
break;
case 6:
System.out.println("Sábado");
break;
case 7:
System.out.println("Domingo");
break;
default:
System.out.println("Día no válido");
}
}
}
Número de día (1-7): 3
Miércoles
Cómo funciona:
- Se evalúa la expresión entre paréntesis (
dia). - Se salta a la etiqueta
casecuyo valor coincide. - Se ejecutan las instrucciones desde ahí hasta encontrar un
break(o el final delswitch). - Si ningún
casecoincide, se salta adefault(si existe).
Figura 5. switch clásico con break y sin break.
9.1. El fallthrough (caída en cascada)
Si olvidas un break, la ejecución continúa en el siguiente case aunque su valor no coincida. A esto se le llama fallthrough:
public class SinBreak {
public static void main(String[] args) {
int dia = 5;
// Se nos han olvidado los break...
switch (dia) {
case 5:
System.out.println("Viernes");
case 6:
System.out.println("Sábado");
case 7:
System.out.println("Domingo");
default:
System.out.println("Día no válido");
}
}
}
Viernes
Sábado
Domingo
Día no válido
Casi siempre es un error, pero a veces se usa a propósito para que varios valores compartan el mismo código:
public class DiasMesClasico {
public static void main(String[] args) {
int mes = 9;
int dias;
// Fallthrough intencionado: varios case comparten el mismo código
switch (mes) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
dias = 31;
break;
case 4: case 6: case 9: case 11:
dias = 30;
break;
case 2:
dias = 28; // sin tener en cuenta los bisiestos
break;
default:
dias = -1; // mes no válido
}
System.out.println("El mes " + mes + " tiene " + dias + " días.");
}
}
Salida: El mes 9 tiene 30 días.
9.2. Reglas del switch
- La expresión puede ser de tipo
int,short,byte,char(y sus envoltorios),Stringo unenum(módulo 14). No puede serlong,float,doublenibooleanen elswitchclásico. - Los valores de los
casedeben ser constantes (literales ofinal) y no pueden repetirse. - No se pueden poner rangos:
case nota >= 5:no compila. Para rangos, usaif-else-if. defaultes opcional, puede ir en cualquier posición (por convención, al final) y no necesitabreaksi es el último.
💡 Consejo: Pon siempre un
default, aunque «sea imposible» llegar a él: te avisará de datos inesperados en lugar de que el programa falle en silencio.
10. Expresiones switch (Java 14+)
El switch clásico tiene dos problemas: el break olvidado y la verbosidad. Desde Java 14 existe una sintaxis nueva con flechas -> que los resuelve. Es la que te recomendamos para código nuevo.
10.1. switch con flechas como sentencia
int nivel = 2;
switch (nivel) {
case 1 -> System.out.println("Nivel fácil");
case 2 -> { // bloque: varias instrucciones
System.out.println("Nivel medio");
System.out.println("Tienes 3 vidas");
}
case 3 -> System.out.println("Nivel difícil");
default -> System.out.println("Nivel desconocido");
}
// Imprime "Nivel medio" y "Tienes 3 vidas". No hace falta break.
Diferencias con el clásico:
- Con
->nunca hay fallthrough: se ejecuta solo lo que hay a la derecha de la flecha. Adiós abreak. - A la derecha va una instrucción o un bloque entre llaves.
- Varios valores se separan con comas en un mismo
case:case 6, 7 -> ....
10.2. switch como expresión: devuelve un valor
La gran novedad es que el switch puede producir un valor, igual que el ternario, y asignarse a una variable. Observa el ; final: es una asignación.
import java.util.Scanner;
public class DiasMes {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Número de mes (1-12): ");
int mes = sc.nextInt();
System.out.print("Año: ");
int anio = sc.nextInt();
int dias = switch (mes) {
case 1, 3, 5, 7, 8, 10, 12 -> 31;
case 4, 6, 9, 11 -> 30;
case 2 -> {
boolean bisiesto = (anio % 4 == 0 && anio % 100 != 0) || anio % 400 == 0;
yield bisiesto ? 29 : 28; // yield devuelve el valor del bloque
}
default -> -1;
};
if (dias == -1) {
System.out.println("Mes no válido");
} else {
System.out.println("El mes " + mes + " de " + anio + " tiene " + dias + " días.");
}
}
}
Número de mes (1-12): 2
Año: 2024
El mes 2 de 2024 tiene 29 días.
Número de mes (1-12): 2
Año: 2025
El mes 2 de 2025 tiene 28 días.
case 1, 3, 5, 7, 8, 10, 12 -> 31;agrupa valores sin fallthrough.- Si una rama necesita varias instrucciones, se usa un bloque y
yieldpara indicar el valor que devuelve.yieldes alswitchlo quereturnes a un método (lo verás en el módulo 07).
10.3. Exhaustividad
Una expresión switch debe cubrir todos los valores posibles, porque siempre tiene que devolver algo. Con un int es imposible enumerar todos sus valores, así que el default es obligatorio:
public class SwitchNoExhaustivo {
public static void main(String[] args) {
int dia = 3;
String nombre = switch (dia) {
case 1 -> "Lunes";
case 2 -> "Martes";
case 3 -> "Miércoles";
};
System.out.println(nombre);
}
}
SwitchNoExhaustivo.java:4: error: the switch expression does not cover all possible input values
String nombre = switch (dia) {
^
1 error
Con un enum (módulo 14) sí puedes cubrir todas las constantes sin default, y el compilador te avisará si algún día añades una nueva y te olvidas de tratarla. Esa comprobación es una de las grandes ventajas del switch moderno.
10.4. Comparativa
| Característica | switch clásico (case X:) | switch con flechas (case X ->) |
|---|---|---|
| Disponible desde | Java 1.0 | Java 14 |
Necesita break | Sí (si no, fallthrough) | No, nunca hay fallthrough |
Varios valores por case | Apilando etiquetas case 1: case 2: | Con comas case 1, 2 -> (también vale case 1, 2: en el clásico desde Java 14) |
| Puede devolver un valor | No (se asigna en cada rama) | Sí, como expresión (con yield en bloques) |
| Exhaustividad comprobada | No | Sí, cuando se usa como expresión |
📘 Concepto: Desde Java 21,
switchtambién admite patrones (por ejemplo,case Integer i when i > 0 ->), que permiten decidir según el tipo de un objeto. Lo estudiarás en el módulo 14, cuando conozcas las clases.
11. switch con String y con char
Desde Java 7, switch admite cadenas. La comparación se hace con equals (distingue mayúsculas de minúsculas), así que conviene normalizar antes con toLowerCase():
import java.util.Scanner;
public class SwitchString {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Escribe un día de la semana: ");
String dia = sc.next().toLowerCase(); // "Sábado" -> "sábado"
String tipo = switch (dia) {
case "lunes", "martes", "miércoles", "jueves", "viernes" -> "laborable";
case "sábado", "domingo" -> "fin de semana";
default -> "desconocido";
};
System.out.println("El " + dia + " es " + tipo + ".");
}
}
Escribe un día de la semana: Sábado
El sábado es fin de semana.
Con char, los valores de los case se escriben entre comillas simples:
import java.util.Scanner;
public class SwitchChar {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Escribe una letra: ");
char letra = sc.next().charAt(0); // primer carácter de lo escrito
switch (letra) {
case 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U' ->
System.out.println("'" + letra + "' es una vocal");
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ->
System.out.println("'" + letra + "' es un dígito");
default ->
System.out.println("'" + letra + "' no es vocal ni dígito");
}
}
}
Escribe una letra: E
'E' es una vocal
💡 Consejo:
sc.next().charAt(0)lee una palabra y se queda con su primer carácter. Es la forma habitual de leer uncharconScanner, que no tienenextChar(). VeráscharAten detalle en el módulo 09.
12. Comparar cadenas: equals y no == (adelanto)
Es muy tentador escribir if (clave == "java"). Parece funcionar en algunas pruebas… y falla en otras. Míralo:
import java.util.Scanner;
public class CompararStrings {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String clave = "java";
System.out.print("Contraseña: ");
String escrita = sc.next();
System.out.println("Con == : " + (escrita == clave));
System.out.println("Con equals: " + escrita.equals(clave));
if (escrita.equals(clave)) {
System.out.println("Acceso concedido");
} else {
System.out.println("Acceso denegado");
}
}
}
Contraseña: java
Con == : false
Con equals: true
Acceso concedido
El usuario escribió exactamente java, pero == dice false. ¿Por qué?
📘 Concepto:
Stringno es un tipo primitivo sino un objeto. Una variableStringno guarda el texto, sino una referencia (la dirección de memoria donde está el objeto).==compara referencias («¿son el mismo objeto?») yequalscompara contenidos («¿tienen los mismos caracteres?»). El texto leído conScanneres un objeto nuevo, distinto del literal"java", aunque contenga lo mismo.
Regla práctica que debes memorizar ya:
| Quiero saber si… | Escribo |
|---|---|
| Dos cadenas tienen el mismo texto | a.equals(b) |
| …sin distinguir mayúsculas | a.equalsIgnoreCase(b) |
Dos primitivos (int, char, double…) son iguales | a == b |
En el módulo 09 entenderás los detalles (el String pool, por qué == a veces «funciona» y cómo comparar en orden alfabético con compareTo).
💡 Consejo: Si una de las cadenas es un literal, ponlo delante:
"java".equals(escrita). Así, siescritafueranull, obtendríasfalseen lugar de unNullPointerException.
13. Errores típicos
13.1. Punto y coma después del if
En if (edad >= 18); { ... }, el ; termina el if con una sentencia vacía. El bloque { ... } que sigue ya no pertenece al if: es un bloque suelto que se ejecuta siempre. Compila sin errores, así que es muy difícil de detectar.
13.2. if sin llaves con varias sentencias
La sangría no tiene significado en Java (no es Python). Sin llaves, el if solo controla la primera sentencia.
13.3. = en lugar de ==
Con números, el compilador te salva:
public class AsignacionEnIf {
public static void main(String[] args) {
int x = 3;
if (x = 5) {
System.out.println("x vale 5");
}
}
}
AsignacionEnIf.java:4: error: incompatible types: int cannot be converted to boolean
if (x = 5) {
^
1 error
Pero con variables boolean compila y es un error silencioso: if (esAdmin = true) asigna true a esAdmin y luego comprueba su valor, que siempre es true.
Los tres errores en un único programa que compila sin quejas:
public class ErroresSilenciosos {
public static void main(String[] args) {
int edad = 12;
// Error 1: punto y coma después del if
if (edad >= 18); {
System.out.println("1) Puedes entrar (¡aunque tengas " + edad + " años!)");
}
// Error 2: if sin llaves con dos sentencias "indentadas"
if (edad >= 18)
System.out.println("2) Mayor de edad");
System.out.println("2) Puedes votar"); // ¡esta línea NO está dentro del if!
// Error 3: = en lugar de == con boolean (compila, pero asigna)
boolean esAdmin = false;
if (esAdmin = true) {
System.out.println("3) Bienvenido, administrador");
}
}
}
1) Puedes entrar (¡aunque tengas 12 años!)
2) Puedes votar
3) Bienvenido, administrador
Ninguna de las tres líneas debería haberse escrito, porque la edad es 12 y esAdmin era false.
13.4. Resumen de errores y soluciones
| Error | Síntoma | Solución |
|---|---|---|
if (x > 0); | El bloque se ejecuta siempre | Quita el ;. IntelliJ lo marca con un aviso: hazle caso |
| Sin llaves | Solo la primera línea depende del if | Pon siempre llaves |
if (x = 5) | incompatible types: int cannot be converted to boolean | Usa == |
if (b = true) | Siempre entra | Escribe simplemente if (b) |
cad == "hola" | Falla con texto leído | cad.equals("hola") |
18 <= x <= 65 | No compila | x >= 18 && x <= 65 |
switch sin break | Se ejecutan varios case | Añade break o usa -> |
Comparar double con == | 0.1 + 0.2 == 0.3 es false | Compara con un margen: Math.abs(a - b) < 1e-9 |
| Ramas mal ordenadas | Una rama «se come» a otras | Ordena de más restrictiva a menos |
💡 Consejo: Para cada condicional que escribas, prueba un valor de cada rama y los valores frontera (si la condición es
nota >= 5, prueba 4.99, 5 y 5.01). La mayoría de los fallos están justo en los límites.
14. Ejemplos completos
14.1. Año bisiesto
Un año es bisiesto si es divisible entre 4, salvo que sea divisible entre 100, en cuyo caso solo lo es si también es divisible entre 400. En pseudocódigo: Si (anio MOD 4 = 0 Y anio MOD 100 <> 0) O anio MOD 400 = 0 Entonces.
import java.util.Scanner;
public class Bisiesto {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Introduce un año: ");
int anio = sc.nextInt();
// Regla del calendario gregoriano:
// divisible entre 4 y no entre 100, o divisible entre 400
boolean bisiesto = (anio % 4 == 0 && anio % 100 != 0) || anio % 400 == 0;
if (bisiesto) {
System.out.println(anio + " es bisiesto (febrero tiene 29 días).");
} else {
System.out.println(anio + " no es bisiesto (febrero tiene 28 días).");
}
}
}
Introduce un año: 2024
2024 es bisiesto (febrero tiene 29 días).
Introduce un año: 1900
1900 no es bisiesto (febrero tiene 28 días).
Introduce un año: 2000
2000 es bisiesto (febrero tiene 29 días).
1900 es divisible entre 4 y entre 100 pero no entre 400: no es bisiesto. 2000 sí lo es porque es divisible entre 400.
14.2. Calculadora con menú
Combina validación con if, una condición compuesta para la división entre cero y una expresión switch:
import java.util.Scanner;
public class Calculadora {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("=== CALCULADORA ===");
System.out.println("1. Sumar 2. Restar 3. Multiplicar 4. Dividir 5. Resto");
System.out.print("Elige una opción: ");
int opcion = sc.nextInt();
if (opcion < 1 || opcion > 5) {
System.out.println("Opción no válida.");
} else {
System.out.print("Primer número: ");
double a = sc.nextDouble();
System.out.print("Segundo número: ");
double b = sc.nextDouble();
if ((opcion == 4 || opcion == 5) && b == 0) {
System.out.println("Error: no se puede dividir entre cero.");
} else {
double resultado = switch (opcion) {
case 1 -> a + b;
case 2 -> a - b;
case 3 -> a * b;
case 4 -> a / b;
default -> a % b; // solo queda la opción 5
};
System.out.printf("Resultado: %.2f%n", resultado);
}
}
}
}
=== CALCULADORA ===
1. Sumar 2. Restar 3. Multiplicar 4. Dividir 5. Resto
Elige una opción: 4
Primer número: 17
Segundo número: 4
Resultado: 4.25
Si en otra ejecución eliges la opción 4 con un segundo número igual a 0, el programa responde Error: no se puede dividir entre cero. sin calcular nada.
📘 Concepto: Con
double, dividir entre cero no lanza excepción:7.0 / 0daInfinityy0.0 / 0daNaN(Not a Number). Conint,7 / 0lanzaArithmeticException. En ambos casos es mejor comprobarlo antes, como hace este programa.
14.3. Tarifas por edad
Un museo cobra 10 € de entrada general. Los menores de 4 años entran gratis, de 4 a 12 pagan la mitad, los mayores de 64 pagan el 60 % y los jóvenes de hasta 25 años con carné joven tienen un 20 % de descuento.
import java.util.Scanner;
public class Tarifas {
public static void main(String[] args) {
final double PRECIO_GENERAL = 10.0;
Scanner sc = new Scanner(System.in);
System.out.print("Edad del visitante: ");
int edad = sc.nextInt();
if (edad < 0 || edad > 120) {
System.out.println("Edad no válida.");
} else {
double precio;
String tarifa;
if (edad < 4) {
tarifa = "Bebé";
precio = 0;
} else if (edad <= 12) {
tarifa = "Infantil";
precio = PRECIO_GENERAL * 0.5;
} else if (edad < 65) {
tarifa = "General";
precio = PRECIO_GENERAL;
System.out.print("¿Tienes carné joven? (1 = sí, 0 = no): ");
int carne = sc.nextInt();
if (carne == 1 && edad <= 25) {
tarifa = "Joven";
precio = PRECIO_GENERAL * 0.8;
}
} else {
tarifa = "Senior";
precio = PRECIO_GENERAL * 0.6;
}
System.out.printf("Tarifa %s: %.2f €%n", tarifa, precio);
}
}
}
Edad del visitante: 8
Tarifa Infantil: 5.00 €
Edad del visitante: 22
¿Tienes carné joven? (1 = sí, 0 = no): 1
Tarifa Joven: 8.00 €
Observa que solo se pregunta por el carné joven cuando tiene sentido (edad entre 13 y 64): es un condicional anidado dentro de una rama de la escalera. Y la constante PRECIO_GENERAL evita repetir el número mágico 10: si el museo sube el precio, solo cambias una línea.
14.4. Ecuación de segundo grado
Para resolver ax² + bx + c = 0 se calcula el discriminante Δ = b² − 4ac:
| Caso | Soluciones |
|---|---|
| a = 0 | No es de segundo grado: bx + c = 0 → x = −c / b (si b ≠ 0) |
| Δ > 0 | Dos soluciones reales: x = (−b ± √Δ) / 2a |
| Δ = 0 | Una solución doble: x = −b / 2a |
| Δ < 0 | Dos soluciones complejas conjugadas |
flowchart TD
A([Inicio]) --> B[/Leer a, b, c/]
B --> C{a == 0}
C -- Sí --> D{b == 0}
D -- Sí --> E{c == 0}
E -- Sí --> E1[/Infinitas soluciones/]
E -- No --> E2[/Sin solución/]
D -- No --> F[/x = -c ÷ b/]
C -- No --> G[d = b² - 4ac]
G --> H{d > 0}
H -- Sí --> H1[/Dos soluciones reales/]
H -- No --> I{d == 0}
I -- Sí --> I1[/Solución doble/]
I -- No --> I2[/Soluciones complejas/]
import java.util.Scanner;
public class Ecuacion {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Coeficientes a, b y c de ax² + bx + c = 0: ");
double a = sc.nextDouble();
double b = sc.nextDouble();
double c = sc.nextDouble();
if (a == 0) {
// No es de segundo grado: queda bx + c = 0
if (b == 0) {
if (c == 0) {
System.out.println("Infinitas soluciones (0 = 0).");
} else {
System.out.println("Sin solución.");
}
} else {
System.out.printf("Ecuación de primer grado. x = %.2f%n", -c / b);
}
} else {
double discriminante = b * b - 4 * a * c;
if (discriminante > 0) {
double x1 = (-b + Math.sqrt(discriminante)) / (2 * a);
double x2 = (-b - Math.sqrt(discriminante)) / (2 * a);
System.out.printf("Dos soluciones reales: x1 = %.2f, x2 = %.2f%n", x1, x2);
} else if (discriminante == 0) {
double x = -b / (2 * a);
System.out.printf("Una solución doble: x = %.2f%n", x);
} else {
double real = -b / (2 * a);
double imaginaria = Math.sqrt(-discriminante) / (2 * a);
System.out.printf("Soluciones complejas: %.2f ± %.2fi%n", real, imaginaria);
}
}
}
}
Cuatro ejecuciones, una por cada caso:
Coeficientes a, b y c de ax² + bx + c = 0: 1 -3 2
Dos soluciones reales: x1 = 2.00, x2 = 1.00
Coeficientes a, b y c de ax² + bx + c = 0: 1 2 1
Una solución doble: x = -1.00
Coeficientes a, b y c de ax² + bx + c = 0: 1 2 5
Soluciones complejas: -1.00 ± 2.00i
Coeficientes a, b y c de ax² + bx + c = 0: 0 2 -4
Ecuación de primer grado. x = 2.00
💡 Consejo: Aquí comparamos
doublecon== 0porque los coeficientes los introduce el usuario y queremos detectar exactamente el cero. Si el discriminante viniera de cálculos con decimales, sería más seguro usar un margen de tolerancia, como viste en la tabla de errores.
14.5. Calificación numérica a texto con switch
La calificación de la sección 5 también se puede resolver con un switch si antes truncas la nota a entero (int entera = (int) nota;) y agrupas valores: case 0, 1, 2, 3, 4 -> "Insuficiente"; case 5 -> "Suficiente"; ... case 9, 10 -> "Sobresaliente";. Es un truco clásico, pero ojo: 10.5 se truncaría a 10 y -0.5 a 0, así que hay que validar el rango antes con un if. Regla general: rangos → if; valores concretos → switch.
15. Ejercicios
Los seis primeros están resueltos; intenta hacerlos antes de mirar la solución. Los resultados que se muestran son de ejecuciones reales con el JDK 25.
Ejercicio 1: El mayor de tres números
Lee tres números enteros y muestra cuál es el mayor.
Ver solución
import java.util.Scanner;
public class MayorDeTres {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Introduce tres números enteros: ");
int a = sc.nextInt();
int b = sc.nextInt();
int c = sc.nextInt();
int mayor;
if (a >= b && a >= c) {
mayor = a;
} else if (b >= c) { // aquí ya sabemos que a no es el mayor
mayor = b;
} else {
mayor = c;
}
System.out.println("El mayor es " + mayor);
}
}
Introduce tres números enteros: 7 12 3
El mayor es 12
En la segunda condición no hace falta comprobar b >= a: si llegamos ahí, a no era el mayor, así que el mayor es b o c. Usar >= en lugar de > hace que el programa funcione también cuando hay empates. Otra solución válida: int mayor = Math.max(a, Math.max(b, c));.
Ejercicio 2: Índice de masa corporal
Lee el peso (kg) y la altura (m), calcula el IMC (peso / altura²) con un decimal y clasifícalo según la OMS: menos de 18.5, bajo peso; hasta 25 (sin incluir), normal; hasta 30 (sin incluir), sobrepeso; 30 o más, obesidad. Valida que los datos sean positivos.
Ver solución
import java.util.Scanner;
public class Imc {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Peso (kg): ");
double peso = sc.nextDouble();
System.out.print("Altura (m): ");
double altura = sc.nextDouble();
if (peso <= 0 || altura <= 0) {
System.out.println("Datos no válidos.");
} else {
double imc = peso / (altura * altura);
String categoria;
if (imc < 18.5) {
categoria = "Bajo peso";
} else if (imc < 25) {
categoria = "Peso normal";
} else if (imc < 30) {
categoria = "Sobrepeso";
} else {
categoria = "Obesidad";
}
System.out.printf("IMC = %.1f -> %s%n", imc, categoria);
}
}
}
Peso (kg): 70
Altura (m): 1.75
IMC = 22.9 -> Peso normal
La validación va primero y el resto del programa queda en el else, así nunca se divide entre una altura de cero. La escalera usa < para que cada límite (18.5, 25, 30) pertenezca a la categoría superior, como indica la clasificación.
Ejercicio 3: Tipo de triángulo
Lee tres lados y di si forman un triángulo (cada lado debe ser positivo y menor que la suma de los otros dos). Si lo forman, indica si es equilátero, isósceles o escaleno.
Ver solución
import java.util.Scanner;
public class TipoTriangulo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Introduce los tres lados: ");
double a = sc.nextDouble();
double b = sc.nextDouble();
double c = sc.nextDouble();
// Desigualdad triangular: cada lado menor que la suma de los otros dos
boolean valido = a > 0 && b > 0 && c > 0
&& a < b + c && b < a + c && c < a + b;
if (!valido) {
System.out.println("Esos lados no forman un triángulo.");
} else if (a == b && b == c) {
System.out.println("Triángulo equilátero");
} else if (a == b || a == c || b == c) {
System.out.println("Triángulo isósceles");
} else {
System.out.println("Triángulo escaleno");
}
}
}
Introduce los tres lados: 5 5 8
Triángulo isósceles
Introduce los tres lados: 1 2 10
Esos lados no forman un triángulo.
El orden de la escalera es importante: el equilátero debe comprobarse antes que el isósceles, porque un triángulo con los tres lados iguales también cumple a == b. Guardar la validez en la variable valido hace que la escalera se lea casi como el enunciado.
Ejercicio 4: El segundo siguiente
Lee una hora en formato horas, minutos y segundos (separados por espacios), valida que sea correcta y muestra la hora un segundo después con el formato hh:mm:ss.
Ver solución
import java.util.Scanner;
public class SegundoSiguiente {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Hora (h m s): ");
int h = sc.nextInt();
int m = sc.nextInt();
int s = sc.nextInt();
if (h < 0 || h > 23 || m < 0 || m > 59 || s < 0 || s > 59) {
System.out.println("Hora no válida.");
} else {
s++;
if (s == 60) {
s = 0;
m++;
if (m == 60) {
m = 0;
h++;
if (h == 24) {
h = 0;
}
}
}
System.out.printf("Un segundo después: %02d:%02d:%02d%n", h, m, s);
}
}
}
Hora (h m s): 23 59 59
Un segundo después: 00:00:00
Los if anidados reflejan el «acarreo»: solo hay que mirar los minutos si los segundos han dado la vuelta, y solo las horas si lo han hecho los minutos. El formato %02d rellena con ceros a la izquierda hasta dos cifras.
Ejercicio 5: Piedra, papel o tijera
Dos jugadores escriben su jugada (piedra, papel o tijera, sin importar mayúsculas). Valida las jugadas e indica quién gana o si hay empate. Usa equals y una expresión switch con String.
Ver solución
import java.util.Scanner;
public class PiedraPapelTijera {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Jugador 1 (piedra/papel/tijera): ");
String j1 = sc.next().toLowerCase();
System.out.print("Jugador 2 (piedra/papel/tijera): ");
String j2 = sc.next().toLowerCase();
boolean validos = (j1.equals("piedra") || j1.equals("papel") || j1.equals("tijera"))
&& (j2.equals("piedra") || j2.equals("papel") || j2.equals("tijera"));
if (!validos) {
System.out.println("Jugada no válida.");
} else if (j1.equals(j2)) {
System.out.println("Empate.");
} else {
// ¿Qué jugada vence a la del jugador 1?
String leGana = switch (j1) {
case "piedra" -> "papel";
case "papel" -> "tijera";
default -> "piedra"; // a la tijera le gana la piedra
};
if (j2.equals(leGana)) {
System.out.println("Gana el jugador 2.");
} else {
System.out.println("Gana el jugador 1.");
}
}
}
}
Jugador 1 (piedra/papel/tijera): Tijera
Jugador 2 (piedra/papel/tijera): papel
Gana el jugador 1.
En lugar de escribir los nueve casos posibles, el switch calcula qué jugada vence a la del jugador 1. Si el jugador 2 ha sacado esa, gana él; si no (y no hay empate), gana el jugador 1. Pensar un poco antes de programar reduce mucho el código.
Ejercicio 6: Ordenar tres números
Lee tres números enteros y muéstralos ordenados de menor a mayor sin usar arrays ni métodos de ordenación, solo condicionales.
Ver solución
import java.util.Scanner;
public class OrdenarTres {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Introduce tres números: ");
int a = sc.nextInt();
int b = sc.nextInt();
int c = sc.nextInt();
// Intercambiamos para conseguir a <= b <= c
int aux;
if (a > b) { // 1) el menor de a y b queda en a
aux = a;
a = b;
b = aux;
}
if (b > c) { // 2) el mayor de todos queda en c
aux = b;
b = c;
c = aux;
}
if (a > b) { // 3) volvemos a colocar a y b
aux = a;
a = b;
b = aux;
}
System.out.println("Ordenados: " + a + " <= " + b + " <= " + c);
}
}
Introduce tres números: 9 2 5
Ordenados: 2 <= 5 <= 9
Para intercambiar dos variables hace falta una variable auxiliar: si hicieras a = b; b = a; perderías el valor original de a. Con tres intercambios condicionales, el mayor acaba en c y los otros dos quedan ordenados. Es la idea del algoritmo de la burbuja que verás en el módulo 08.
Ejercicio 7: Valor absoluto (propuesto)
Lee un número double y muestra su valor absoluto sin usar Math.abs. Hazlo dos veces: con if y con el operador ternario.
Ejercicio 8: Nómina con horas extra (propuesto)
Lee las horas trabajadas en una semana y el precio por hora. Las primeras 40 horas se pagan al precio normal y las que pasen de 40 se pagan un 50 % más caras. Si el sueldo bruto supera los 600 €, se retiene un 15 %; si no, un 8 %. Muestra el bruto, la retención y el neto con dos decimales.
Ejercicio 9: Fecha válida (propuesto)
Lee día, mes y año y di si la fecha es válida. Usa una expresión switch para obtener los días del mes y ten en cuenta los años bisiestos. Prueba al menos con 29/2/2024 (válida), 29/2/2025 (no válida), 31/4/2026 (no válida) y 0/1/2026 (no válida).
Ejercicio 10: Estación del año (propuesto)
Lee un mes (1-12) y un día y muestra la estación del año en el hemisferio norte, tomando como inicio de cada estación el día 21 de marzo, junio, septiembre y diciembre. Pista: primero decide por el mes con un switch y, en los meses de cambio, usa un if con el día.
Ejercicio 11: Impuesto por tramos (propuesto)
Calcula el impuesto de una renta anual con este sistema de tramos (cada porcentaje se aplica solo a la parte de la renta que cae en su tramo): hasta 12 450 €, 19 %; de 12 450 a 20 200 €, 24 %; de 20 200 a 35 200 €, 30 %; más de 35 200 €, 37 %. Por ejemplo, con 15 000 € se paga 12 450 · 0,19 + 2 550 · 0,24. Muestra el impuesto total y el tipo medio (impuesto / renta).
Ejercicio 12: Menú de conversión de unidades (propuesto)
Muestra un menú con estas opciones: 1) kilómetros a millas, 2) millas a kilómetros, 3) grados Celsius a Fahrenheit, 4) Fahrenheit a Celsius. Lee la opción y el valor, y muestra el resultado con dos decimales usando una expresión switch. Si la opción no existe, muestra un mensaje de error sin pedir el valor.
Resumen
| Concepto | Sintaxis / idea clave |
|---|---|
| Condición | Expresión boolean: x > 0, a == b, ok && !fin |
| Operadores lógicos | && (y), \|\| (o), ! (no); evaluación en cortocircuito |
| Rango | x >= 1 && x <= 10 (nunca 1 <= x <= 10) |
if | if (cond) { ... } |
if-else | if (cond) { ... } else { ... }: se ejecuta exactamente uno |
| Escalera | if ... else if ... else: la primera condición verdadera gana |
| Anidamiento | if dentro de if; el else va con el if más cercano sin else |
| Bloque y ámbito | Una variable vive desde su declaración hasta la } de su bloque |
| Ternario | var = cond ? valor1 : valor2; |
switch clásico | case X: … break; + default:; sin break hay fallthrough |
switch con flechas (Java 14) | case X, Y -> ...; sin break ni fallthrough |
Expresión switch | int d = switch (m) { case 2 -> 28; default -> 30; };, yield en bloques, exhaustiva |
Tipos en switch | int, char, String, enum (y patrones desde Java 21) |
Comparar String | a.equals(b), a.equalsIgnoreCase(b); nunca == |
| Errores típicos | ; tras el if, falta de llaves, = por ==, break olvidado |