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.
Input and control flow in Java — Scanner, if/else and switch from scratch
Control flow in Java covers two things that always go together in FP2: reading user input with Scanner and making decisions with if/else and switch. If you know Python you already know the logic. If you’ve seen C’s switch in IC2, Java’s is almost identical. What’s new is Scanner and the buffer problem, a silent trap that breaks entire programs if you don’t know it exists.
Importing classes in Java
import java.util.Scanner; // before the class declaration
public class MyProgram {
public static void main(String[] args) {
// Scanner available here
}
}
VS Code adds imports automatically, but knowing they exist matters.
What is Scanner and how to create it
# Python — one function for everything
name = input("Enter your name: ")
age = int(input("Enter your age: "))
// Java — create a Scanner object
import java.util.Scanner;
public class ReadData {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = sc.nextLine();
System.out.print("Enter your age: ");
int age = sc.nextInt();
System.out.println("Hello " + name + ", you are " + age);
sc.close();
}
}
new Scanner(System.in) creates a Scanner object connected to the keyboard. System.in is standard input, just as System.out is standard output.
Scanner methods — one per type
sc.nextInt() // reads int sc.nextLong() // reads long sc.nextDouble() // reads double sc.nextBoolean() // reads true/false sc.next() // reads one word (stops at space) sc.nextLine() // reads full line (until Enter)
next() vs nextLine(): if the user types «Sergio Medina» and presses Enter, next() returns "Sergio", nextLine() returns "Sergio Medina".
The buffer problem — Scanner’s most common trap
When the user types a number and presses Enter, nextInt() reads the number but leaves the newline character \n in the buffer. A subsequent nextLine() reads that leftover \n instead of waiting for user input — returning an empty string:
Scanner sc = new Scanner(System.in);
System.out.print("Age: ");
int age = sc.nextInt(); // reads "22", leaves "\n" in buffer
System.out.print("Name: ");
String name = sc.nextLine(); // reads the leftover "\n" → name = ""
// program doesn't wait for user input
System.out.println("Hello " + name); // → "Hello "
The program seems to skip the name question. It didn’t, it answered automatically with the leftover Enter.
The fix, add an empty sc.nextLine() after any nextInt(), nextDouble() etc. to consume the leftover \n:
int age = sc.nextInt(); sc.nextLine(); // ← cleaner — consumes leftover "\n" String name = sc.nextLine(); // now waits for user input
Rule: whenever you use nextInt(), nextDouble() etc. and then need nextLine(), always add an empty sc.nextLine() between them.
Alternative read everything as String and convert:
int age = Integer.parseInt(sc.nextLine()); // no buffer problem String name = sc.nextLine();
if/else — same logic as Python, different syntax
# Python
if grade >= 9:
print("Distinction")
elif grade >= 7:
print("Merit")
elif grade >= 5:
print("Pass")
else:
print("Fail")
// Java
if (grade >= 9) {
System.out.println("Distinction");
} else if (grade >= 7) {
System.out.println("Merit");
} else if (grade >= 5) {
System.out.println("Pass");
} else {
System.out.println("Fail");
}
Key differences from Python:
- Condition in parentheses
(grade >= 9)— required elif→else if(two words)- Curly braces
{ }delimit blocks — no colons
Logical operators:
# Python: and, or, not
// Java: &&, ||, !
if (a > 0 && b > 0) { ... }
if (a > 0 || b > 0) { ... }
if (!active) { ... }
Ternary operator
# Python result = "Pass" if grade >= 5 else "Fail"
// Java — condition ? value_if_true : value_if_false String result = (grade >= 5) ? "Pass" : "Fail"; int max = (a > b) ? a : b;
Use for simple assignments, not for complex nested logic.
switch/case — comparison with C
If you’ve used C’s switch in IC2, Java’s is nearly identical, same structure, same break, same default. The main addition: Java allows Strings:
// C — integers and chars only
switch (option) {
case 1: printf("Option 1\n"); break;
case 2: printf("Option 2\n"); break;
default: printf("Invalid\n");
}
// Java — integers, chars, Strings and enums
switch (option) {
case 1:
System.out.println("Option 1");
break;
case 2:
System.out.println("Option 2");
break;
default:
System.out.println("Invalid");
}
Why break is required — fall-through
Without break, Java continues executing the next case even if its value doesn’t match, same as C:
int day = 2;
switch (day) {
case 2:
System.out.println("Tuesday"); // executes
// no break — falls through
case 3:
System.out.println("Wednesday"); // also executes
break;
}
// Output: Tuesday
// Wednesday
Intentional fall-through, multiple cases, same action:
switch (day) {
case 1: case 2: case 3: case 4: case 5:
System.out.println("Weekday");
break;
case 6: case 7:
System.out.println("Weekend");
break;
}
switch with String — what C can’t do
String command = "quit";
switch (command) {
case "help":
System.out.println("Showing help...");
break;
case "quit":
System.out.println("Goodbye");
break;
default:
System.out.println("Unknown command: " + command);
}
Java uses .equals() internally to compare Strings in switch, so it works correctly.
switch vs if/else — when to use each
Use switch: comparing one variable against exact fixed values
3+ distinct cases
int, char, or String values
Use if/else: ranges (grade >= 5, grade < 7...)
conditions mixing multiple variables
1-2 cases
Quick summary
// IMPORT
import java.util.Scanner;
// CREATE
Scanner sc = new Scanner(System.in);
// READ METHODS
sc.nextInt() sc.nextDouble() sc.nextLong()
sc.next() sc.nextLine() sc.nextBoolean()
// BUFFER FIX
int n = sc.nextInt();
sc.nextLine(); // ← cleaner — always here before nextLine()
String s = sc.nextLine();
// CLOSE
sc.close();
// IF/ELSE
if (condition) { ... }
else if (condition) { ... }
else { ... }
// LOGICAL OPERATORS
// Python: and or not
// Java: && || !
// TERNARY
type var = (condition) ? valueIfTrue : valueIfFalse;
// SWITCH — same as C but accepts String
switch (variable) {
case value1:
// code
break; // required — prevents fall-through
case value2:
// code
break;
default:
// code
}
// DIFFERENCES FROM C
// Java accepts String in switch (C does not)
// Fall-through works the same as C
// break required the same as C

Un comentario