Entrada y control de flujo en Java — Scanner, if/else y switch desde cero
El control de flujo en Java cubre dos cosas que en FP2 van siempre juntas: cómo leer datos del usuario con Scanner y cómo tomar decisiones con if/else y switch. Si vienes de Python ya conoces la lógica, las condiciones funcionan igual. Si además has visto el switch de C en IC2, el de Java te va a resultar casi idéntico. Lo que es nuevo es el Scanner y el problema del buffer, esa trampa silenciosa que destroza programas enteros si no sabes que existe.
Tabla de Contenidos
Importar clases en Java — la primera vez que ves import
Antes de usar Scanner hay que importarlo. En Python importabas módulos con import. En Java importas clases con import también, pero la sintaxis es diferente y va siempre al principio del archivo, antes de la clase:
# Python import math from math import sqrt
// Java — import va antes de la clase
import java.util.Scanner;
public class MiPrograma {
public static void main(String[] args) {
// aquí ya puedes usar Scanner
}
}
java.util.Scanner es la ruta completa de la clase, java.util es el paquete (equivalente a un módulo de Python) y Scanner es la clase dentro de ese paquete.
VS Code con la extensión Java añade el import automáticamente cuando empiezas a escribir Scanner, pero tienes que saber que existe para entender qué hace.
También puedes importar todo el paquete con *:
import java.util.*; // importa todas las clases de java.util
En FP2 verás las dos formas. La importación específica (import java.util.Scanner) es mejor práctica porque deja claro qué clases estás usando.
Qué es Scanner y cómo crearlo
Scanner es la clase de Java para leer entrada del usuario, el equivalente de input() en Python. Para usarlo hay que crear un objeto Scanner conectado a la entrada estándar (System.in: el teclado):
# Python — una sola función para todo
nombre = input("Introduce tu nombre: ")
edad = int(input("Introduce tu edad: "))
// Java — crear un Scanner y usarlo para leer
import java.util.Scanner;
public class LeerDatos {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); // crea el Scanner
System.out.print("Introduce tu nombre: ");
String nombre = sc.nextLine(); // lee texto
System.out.print("Introduce tu edad: ");
int edad = sc.nextInt(); // lee entero
System.out.println("Hola " + nombre + ", tienes " + edad + " años");
sc.close(); // cierra el Scanner al terminar
}
}
new Scanner(System.in) crea un objeto Scanner conectado al teclado. System.in es la entrada estándar, igual que System.out era la salida estándar. La palabra new crea un objeto nuevo, la verás constantemente en Java.
Por qué hay nextInt(), nextDouble(), nextLine()… — y cuándo usar cada uno
En Python input() siempre devuelve un String y tú convertías con int() o float(). En Java Scanner tiene métodos específicos para cada tipo, y esto es importante porque cada método lee exactamente ese tipo del teclado:
sc.nextInt() // lee un entero (int) sc.nextLong() // lee un entero largo (long) sc.nextDouble() // lee un decimal (double) sc.nextFloat() // lee un decimal simple (float) sc.nextBoolean() // lee true o false (boolean) sc.next() // lee una palabra (String hasta el espacio) sc.nextLine() // lee una línea completa (String hasta el Enter)
La diferencia entre next() y nextLine():
// Si el usuario escribe "Sergio Medina" y pulsa Enter: String palabra = sc.next(); // → "Sergio" (para en el espacio) String linea = sc.nextLine(); // → "Sergio Medina" (lee todo hasta Enter)
Para leer un nombre completo con espacios siempre usa nextLine(). Para leer una sola palabra sin espacios puedes usar next().
El problema del buffer — la trampa más común de Scanner
Aquí está el problema que más confunde a los estudiantes de FP2 y que hace que los programas parezcan saltarse preguntas.
Cuando el usuario escribe un número y pulsa Enter, nextInt() lee el número pero deja el carácter de fin de línea \n (el Enter) en el buffer. Si después llamas a nextLine(), ese método lee el \n que quedó, y devuelve una cadena vacía en vez de esperar a que el usuario escriba algo.
Scanner sc = new Scanner(System.in);
System.out.print("Edad: ");
int edad = sc.nextInt(); // el usuario escribe "22" y pulsa Enter
// nextInt() lee "22" pero deja "\n" en el buffer
System.out.print("Nombre: ");
String nombre = sc.nextLine(); // ← lee el "\n" que quedó → nombre = ""
// el programa NO espera que el usuario escriba
System.out.println("Hola " + nombre); // → "Hola " — nombre está vacío
El programa parece que se salta la pregunta del nombre. En realidad sí preguntó, pero respondió automáticamente con el Enter que quedó en el buffer.
La solución, añadir un sc.nextLine() vacío después de cualquier nextInt(), nextDouble() o similar para consumir el \n sobrante:
Scanner sc = new Scanner(System.in);
System.out.print("Edad: ");
int edad = sc.nextInt();
sc.nextLine(); // ← consume el "\n" sobrante — línea limpiadora
System.out.print("Nombre: ");
String nombre = sc.nextLine(); // ahora sí espera al usuario
System.out.println("Hola " + nombre + ", tienes " + edad + " años");
La regla práctica: siempre que uses nextInt(), nextDouble() u otro método de tipo, y después necesites leer un String con nextLine(), añade un sc.nextLine() vacío entre los dos.
int numero = sc.nextInt(); sc.nextLine(); // limpiador — siempre aquí si viene nextLine() después String texto = sc.nextLine();
Otra solución alternativa que evita el problema completamente, leer todo como String y convertir:
System.out.print("Edad: ");
int edad = Integer.parseInt(sc.nextLine()); // lee la línea y convierte
System.out.print("Nombre: ");
String nombre = sc.nextLine(); // no hay problema de buffer
Esta segunda forma es más segura y muchos programadores de Java la prefieren. En FP2 verás las dos.
El if/else en Java — igual que en Python pero con llaves
La lógica de if/else es idéntica a Python. Lo que cambia es la sintaxis, paréntesis alrededor de la condición y llaves en vez de indentación:
# Python
nota = 7.5
if nota >= 9:
print("Matrícula")
elif nota >= 7:
print("Notable")
elif nota >= 5:
print("Aprobado")
else:
print("Suspenso")
java
// Java
double nota = 7.5;
if (nota >= 9) {
System.out.println("Matrícula");
} else if (nota >= 7) {
System.out.println("Notable");
} else if (nota >= 5) {
System.out.println("Aprobado");
} else {
System.out.println("Suspenso");
}
Las diferencias respecto a Python:
- La condición va entre paréntesis
(nota >= 9), obligatorio elifen Python =else ifen Java, dos palabras separadas- Las llaves
{ }delimitan cada bloque - No hay dos puntos
:al final de la condición
Los operadores de comparación son exactamente iguales que en Python:
== // igual (para primitivos — para objetos usa .equals()) != // distinto > // mayor que < // menor que >= // mayor o igual <= // menor o igual
Los operadores lógicos cambian de nombre respecto a Python.
# Python if a > 0 and b > 0: if a > 0 or b > 0: if not activo:
// Java
if (a > 0 && b > 0) { // and → &&
if (a > 0 || b > 0) { // or → ||
if (!activo) { // not → !
If sin llaves — cuando es correcto y cuando es trampa en el control de flujo en Java
Si el bloque tiene una sola instrucción puedes omitir las llaves, igual que en C:
if (nota >= 5)
System.out.println("Aprobado"); // correcto — una sola instrucción
if (nota >= 5)
System.out.println("Aprobado");
System.out.println("Enhorabuena"); // TRAMPA — esta línea NO está en el if
// se ejecuta siempre
En el segundo ejemplo la indentación engaña, parece que las dos líneas están dentro del if pero sin llaves solo la primera lo está. La segunda se ejecuta siempre independientemente de la condición.
La recomendación para FP2: usa siempre llaves, aunque el bloque tenga una sola línea. Evita problemas y el código es más claro.
El operador ternario — if/else en una línea
Java tiene el operador ternario, una forma compacta de escribir un if/else que devuelve un valor:
# Python — expresión condicional calificacion = "Aprobado" if nota >= 5 else "Suspenso"
// Java — operador ternario // condición ? valor_si_verdadero : valor_si_falso String calificacion = (nota >= 5) ? "Aprobado" : "Suspenso";
Se lee así: «si nota >= 5 entonces "Aprobado", si no "Suspenso"«.
int max = (a > b) ? a : b; // el mayor de dos números String paridad = (n % 2 == 0) ? "par" : "impar"; System.out.println((x > 0) ? "positivo" : "no positivo");
Úsalo para asignaciones simples. Cuando la lógica es más compleja usa if/else normal, el ternario anidado es ilegible:
// MAL — ternario anidado, difícil de leer String nota = (n >= 9) ? "Matrícula" : (n >= 7) ? "Notable" : (n >= 5) ? "Aprobado" : "Suspenso"; // BIEN — if/else normal para lógica compleja String nota; if (n >= 9) nota = "Matrícula"; else if (n >= 7) nota = "Notable"; else if (n >= 5) nota = "Aprobado"; else nota = "Suspenso";
Switch/case en Java — comparativa con C
Si has visto el switch de C en IC2, el de Java te va a resultar casi idéntico, misma estructura, mismo break, mismo default. La diferencia principal es que Java permite usar Strings además de enteros:
// C — switch solo con enteros y chars
switch (opcion) {
case 1:
printf("Opción 1\n");
break;
case 2:
printf("Opción 2\n");
break;
default:
printf("Opción inválida\n");
}
// Java — switch con enteros, chars, Strings y enums
switch (opcion) {
case 1:
System.out.println("Opción 1");
break;
case 2:
System.out.println("Opción 2");
break;
default:
System.out.println("Opción inválida");
}
La estructura es prácticamente idéntica a C. Las diferencias:
- Java admite
Stringen el switch (C no) System.out.printlnen vez deprintf- Por lo demás — igual
Por qué break es obligatorio — el fall-through
El break al final de cada case no es decorativo, es lo que hace que el switch salga del bloque después de ejecutar ese caso. Sin break, Java continúa ejecutando el siguiente case aunque su condición no se cumpla, esto se llama fall-through y es el mismo comportamiento que en C:
int dia = 2;
switch (dia) {
case 1:
System.out.println("Lunes");
// sin break — caemos al siguiente
case 2:
System.out.println("Martes");
// sin break — caemos al siguiente
case 3:
System.out.println("Miércoles");
break;
case 4:
System.out.println("Jueves");
break;
}
// dia = 2, pero la salida es:
// Martes
// Miércoles
// (cayó desde case 2 hasta el break en case 3)
// Con break — correcto
int dia = 2;
switch (dia) {
case 1:
System.out.println("Lunes");
break;
case 2:
System.out.println("Martes"); // solo esto se ejecuta
break;
case 3:
System.out.println("Miércoles");
break;
default:
System.out.println("Día inválido");
}
// → Martes
El fall-through a veces se usa intencionadamente cuando varios casos deben ejecutar el mismo código:
// Fall-through intencional — varios casos, misma acción
switch (dia) {
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println("Día laborable");
break;
case 6:
case 7:
System.out.println("Fin de semana");
break;
}
Switch con String — lo que C no puede hacer
String comando = "salir";
switch (comando) {
case "ayuda":
System.out.println("Mostrando ayuda...");
break;
case "salir":
System.out.println("Hasta luego");
break;
case "inicio":
System.out.println("Volviendo al inicio...");
break;
default:
System.out.println("Comando desconocido: " + comando);
}
// → Hasta luego
Internamente Java usa .equals() para comparar los Strings del switch, por eso funciona correctamente. No uses variables de tipo long, float o double en switch, solo int, char, String y enum.
Switch vs if/else — cuándo usar cada uno
Usa switch cuando: - Comparas una variable contra valores fijos y concretos - Hay 3 o más casos distintos - Los valores son enteros, chars o Strings Usa if/else cuando: - Las condiciones son rangos (nota >= 5, nota < 7...) - Las condiciones mezclan varias variables - Solo hay 1 o 2 casos
// switch — perfecto para valores exactos
switch (mes) {
case 1: System.out.println("Enero"); break;
case 2: System.out.println("Febrero"); break;
// ...
}
// if/else — necesario para rangos
if (nota >= 9) {
System.out.println("Matrícula");
} else if (nota >= 7) {
System.out.println("Notable");
}
// esto NO se puede hacer con switch
Un programa completo con todo junto
import java.util.Scanner;
public class CalculadoraNotas {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("=== Calculadora de notas ===\n");
System.out.print("Nombre del estudiante: ");
String nombre = sc.nextLine();
System.out.print("Nota del primer parcial (0-10): ");
double parcial1 = sc.nextDouble();
System.out.print("Nota del segundo parcial (0-10): ");
double parcial2 = sc.nextDouble();
sc.nextLine(); // limpiador de buffer
double media = (parcial1 + parcial2) / 2;
// Clasificación con if/else
String calificacion;
if (media >= 9) {
calificacion = "Matrícula de Honor";
} else if (media >= 7) {
calificacion = "Notable";
} else if (media >= 5) {
calificacion = "Aprobado";
} else {
calificacion = "Suspenso";
}
// Operador ternario para estado
String estado = (media >= 5) ? "APROBADO" : "SUSPENSO";
// Salida formateada
System.out.println("\n--- Resultado ---");
System.out.printf("Estudiante: %s%n", nombre);
System.out.printf("Parcial 1: %.2f%n", parcial1);
System.out.printf("Parcial 2: %.2f%n", parcial2);
System.out.printf("Media: %.2f%n", media);
System.out.printf("Nota: %s%n", calificacion);
System.out.printf("Estado: %s%n", estado);
// Switch para mensaje según calificación
System.out.print("\nMensaje: ");
switch (calificacion) {
case "Matrícula de Honor":
System.out.println("¡Excelente trabajo!");
break;
case "Notable":
System.out.println("Muy bien, sigue así.");
break;
case "Aprobado":
System.out.println("Aprobado, pero puedes mejorar.");
break;
default:
System.out.println("Ánimo, a por la próxima convocatoria.");
}
sc.close();
}
}
Ejemplo de ejecución:
=== Calculadora de notas === Nombre del estudiante: Sergio Nota del primer parcial (0-10): 7.5 Nota del segundo parcial (0-10): 8.0 --- Resultado --- Estudiante: Sergio Parcial 1: 7.50 Parcial 2: 8.00 Media: 7.75 Nota: Notable Estado: APROBADO Mensaje: Muy bien, sigue así.
Resumen rápido
// IMPORTAR Scanner
import java.util.Scanner; // siempre antes de la clase
// CREAR Scanner
Scanner sc = new Scanner(System.in);
// MÉTODOS DE LECTURA
sc.nextInt() // lee int
sc.nextDouble() // lee double
sc.nextLong() // lee long
sc.next() // lee palabra (hasta espacio)
sc.nextLine() // lee línea completa (hasta Enter)
sc.nextBoolean() // lee true/false
// PROBLEMA DEL BUFFER — solución
int n = sc.nextInt();
sc.nextLine(); // ← limpiador obligatorio antes de nextLine()
String s = sc.nextLine();
// CERRAR Scanner
sc.close();
// IF/ELSE
if (condicion) {
...
} else if (otraCondicion) {
...
} else {
...
}
// elif de Python = else if en Java
// OPERADORES LÓGICOS
// Python: and, or, not
// Java: &&, ||, !
// OPERADOR TERNARIO
tipo var = (condicion) ? valorSiVerdadero : valorSiFalso;
String s = (nota >= 5) ? "Aprobado" : "Suspenso";
// SWITCH — igual que en C pero admite String
switch (variable) {
case valor1:
// código
break; // obligatorio — sin él hay fall-through
case valor2:
// código
break;
default: // equivale al else — opcional
// código
}
// SWITCH vs IF/ELSE
// switch → valores exactos (int, char, String)
// if/else → rangos y condiciones complejas
// DIFERENCIAS CON C
// Java admite String en switch (C no)
// El fall-through funciona igual que en C
// break obligatorio igual que en C
En el próximo artículo vemos los bucles, for, for each y while en Java comparados con Python y C.
¿Te ha servido este artículo? Así puedes apoyar SergioLearns →

Un comentario