9. Entrada de información: java.lang.IO
UD1 — Fundamentos de Programación
IES Thiar · Curso 2026 - 2027
| Aspecto | Valor |
|---|---|
| Resultado de aprendizaje | RA1 — Reconoce la estructura de un programa informático, identificando y relacionando los elementos propios del lenguaje de programación utilizado. |
| Criterios de evaluación cubiertos | CE 1.5 — Se ha modificado el código de un programa para crear y utilizar variables (en este caso, leyéndolas desde la entrada estándar). |
| Marco normativo | RD 405/2023 · RD 450/2010 · RD 659/2023 |
| Tecnología base | Java 25 LTS — java.lang.IO (JEP 512), java.util.Scanner (Java 5+). |
Introducción de la sección
Hasta ahora tus programas solo producían salida: System.out.println mostraba texto en la consola. Pero un programa interesante necesita recibir información del usuario: un nombre, una edad, dos números para sumarlos... En esta sección vas a aprender a leer lo que el usuario escribe por teclado usando la nueva clase java.lang.IO de Java 25, que simplifica muchísimo la entrada/salida. Verás también una breve introducción a Scanner, una clase más clásica que sigue siendo útil y que encontrarás en cualquier código heredado.
Suponemos que ya dominas la conversión de tipos (Sección 8: Integer.parseInt, Double.parseDouble, Boolean.parseBoolean), porque la entrada por teclado siempre devuelve texto y muchas veces necesitas convertirlo a número. La gestión de errores (qué pasa si el usuario escribe "abc" cuando esperas un número) requiere try-catch, que se ve en UD3 Sección 8; por ahora nos quedamos en el "camino feliz" y verás dos técnicas sencillas para ir tirando sin excepciones.
9.1 La clase java.lang.IO (JEP 512, Java 25)
Qué es y de dónde viene
java.lang.IO es una clase nueva introducida en Java 25 como parte de la JEP 512 (Compact Source Files and Instance Main Methods). Su objetivo es simplificar la entrada/salida estándar para que no tengas que escribir System.out.println(...) ni instanciar un Scanner a mano para leer una línea.
IO es una clase con métodos estáticos: no necesitas crear un objeto, llamas directamente a IO.algo(). Al estar en el paquete java.lang (como String, System o Math), no requiere import: la usas directamente.
Métodos principales
| Método | Qué hace | Devuelve |
|---|---|---|
IO.println() |
Imprime una línea vacía | void |
IO.println(Object x) |
Imprime x y salta de línea |
void |
IO.print(Object x) |
Imprime x sin saltar de línea |
void |
IO.readln() |
Lee una línea del teclado | String |
IO.readln(String prompt) |
Imprime prompt y lee una línea |
String |
Las dos sobrecargas de readln (con y sin prompt) son las que usarás siempre. La versión con prompt es muy cómoda: imprime el mensaje y lee en una sola llamada.
Por qué readln siempre devuelve String
El teclado siempre produce texto. Aunque el usuario pulse 2 3 Enter, lo que Java recibe es la cadena "23", no el número 23. Si necesitas un int, convierte el String con Integer.parseInt(...) (Sección 8). En la subsección 9.3 verás este patrón en detalle.
9.2 Leer texto: nombre, ciudad, etc.
Lo más sencillo es leer un String y usarlo tal cual:
Ejecución:
Fíjate en el detalle: el prompt (el texto "¿Cómo te llamas? ") lo pasas como argumento a readln, no con print aparte. Es un atajo que ahorra una línea y queda muy legible.
Con formatted y text blocks
Si quieres saludar con un formato más vistoso, combinas readln con lo aprendido en la Sección 5:
9.3 Leer números: texto + conversión
El patrón básico para leer un número es:
- Leer el texto con
IO.readln(...)(devuelveString). - Convertir el
Stringal tipo numérico conInteger.parseInt,Double.parseDouble, etc. (Sección 8).
Ejecución:
La trampa del formato estricto
Integer.parseInt es estricto: solo admite dígitos (y un signo + o - opcional al inicio). Cualquier otra cosa —espacios, comas, letras— hace que el programa termine con NumberFormatException.
La trampa del separador decimal en double
Para double el asunto es más delicado porque en España el separador decimal es la coma, pero Java espera el punto:
En la Sección 8 ya vimos que se puede forzar el locale con String.format(Locale.US, ...), pero para entrada lo más sencillo es reemplazar la coma por punto antes de parsear. Lo verás en el ejemplo integrador (9.6).
Por qué no lo gestionamos aquí
Si el usuario escribe "abc" cuando esperas un número, el programa termina con un error. La forma profesional de gestionarlo —mostrar un mensaje y volver a pedir el dato— requiere try-catch, que se ve en UD3 Sección 8. Por ahora asumimos el "camino feliz" (el usuario escribe lo que le pides). En la subsección 9.5 verás dos técnicas de validación sin excepciones para ir tirando hasta entonces.
Boolean.parseBoolean: el que no lanza nunca
Es el único parseXxx que no revienta nunca: devuelve false para cualquier cosa que no sea "true" (case-insensitive). Útil, pero ten cuidado: eso significa que "no", "sí" y " abc " todos se interpretan como false. Para pedir confirmaciones tipo S/N necesitas comparar el String a mano con .equalsIgnoreCase("s").
9.4 Scanner: la alternativa clásica (introducción breve)
Antes de Java 25, la forma estándar de leer entrada era la clase java.util.Scanner, introducida en Java 5. La verás en cualquier código heredado, en tutoriales antiguos y en la mayoría de ejemplos de Internet, así que conviene que la reconozcas y sepas usarla a nivel básico.
Uso básico
Diferencia clave con IO.readln + parseInt
| Operación | Con java.lang.IO |
Con Scanner |
|---|---|---|
| Leer un entero | int n = Integer.parseInt(IO.readln("n: ")); |
int n = sc.nextInt(); |
Leer un double |
double d = Double.parseDouble(IO.readln("d: ")); |
double d = sc.nextDouble(); |
| Leer una línea | String s = IO.readln("s: "); |
String s = sc.nextLine(); |
| ¿Crea objetos? | No, son métodos estáticos | Sí, hay que instanciar Scanner |
| ¿Depende del locale? | No (trabajas con String) |
Sí (afecta al separador decimal) |
| ¿Hay que cerrarlo? | No | En principio, sc.close() |
La gran ventaja de Scanner es que combina lectura y conversión en un solo método (nextInt lee y convierte). La gran ventaja de IO es que es más simple y no tiene efectos de locale: tú haces la conversión, así que controlas el formato.
Trampa 1: el locale en Scanner
Scanner usa el locale del sistema para interpretar números. En un equipo configurado en español, sc.nextDouble() espera la coma como separador decimal:
Esto es fuente de confusión para principiantes (escribes el punto como has visto en tus apuntes y no funciona). Si quieres que Scanner entienda siempre el punto, fuerza el locale:
Trampa 2: nextInt deja el Enter en el buffer
Cuando mezclas nextInt() (que lee un número pero deja el salto de línea sin consumir) con nextLine() (que lee hasta el próximo salto), obtienes un comportamiento sorprendente:
Solución: tras un nextInt() (o nextDouble()), llama a un nextLine() "basura" para consumir el salto antes de leer texto:
Con IO.readln este problema no existe porque siempre lee líneas completas.
Cuál usar
En este curso usaremos IO.readln + parseInt como estilo preferido (más limpio, sin sorpresas de locale ni buffer). Pero conviene que sepas leer Scanner porque lo verás en código de compañeros, en Stack Overflow y en la mayoría de tutoriales Java que existen en Internet. A partir de UD3, cuando veamos try-catch, verás también el patrón try (Scanner sc = new Scanner(System.in)) { ... } para cerrarlo automáticamente.
9.5 ¿Y si el usuario escribe mal? (sin try-catch)
Si el usuario teclea "abc" cuando le pides un número, Integer.parseInt("abc") lanza NumberFormatException y el programa termina. La gestión profesional de este error requiere try-catch, que se ve en UD3 Sección 8.
9.6 Ejemplo integrador: calculadora de propina
Ejecución:
Fíjate en .replace(",", "."): como el usuario español escribirá la coma decimal pero Double.parseDouble espera el punto, este truco convierte la entrada antes de parsearla. Sencillo y suficiente para UD1.
Errores comunes
| Error | Síntoma | Causa | Solución |
|---|---|---|---|
Asignar readln a un int |
"int n = IO.readln(...)" no compila |
readln devuelve String, no int |
Convierte: Integer.parseInt(IO.readln(...)) |
| Separador decimal equivocado | Double.parseDouble("3,14") revienta |
Java espera punto | .replace(",", ".") antes de parsear |
Mezclar Scanner.nextInt con nextLine |
El nextLine se salta |
El Enter del nextInt queda en el buffer |
sc.nextLine() "basura" después de cada nextInt |
Scanner con locale español |
nextDouble() falla con 3.14 |
Espera coma decimal | .useLocale(Locale.US) |
| No gestionar entrada inválida | Programa revienta con NumberFormatException |
No hay validación | Técnicas de 9.6 o, mejor, try-catch en UD3 |
Ejercicios propuestos
Ejercicio 9.1 (saludar). Escribe un programa que pida al usuario su nombre y su ciudad y muestre por pantalla "Hola, [nombre] de [ciudad]".
Ejercicio 9.2 (área rectángulo). Pide la base y la altura de un rectángulo (como double), calcula el área y muéstrala con dos decimales usando formatted. Recuerda el .replace(",", ".") si el usuario escribe con coma.
Ejercicio 9.3 (conversor de temperatura). Pide una temperatura en grados Celsius y muéstrala en Fahrenheit (F = C × 9/5 + 32). Maneja la coma decimal del input.
Ejercicio 9.4 (media de tres notas). Pide tres notas (enteros de 0 a 10), calcula la media y muestra "Aprobado" si es ≥ 5 o "Suspenso" si no, usando el operador ternario. Sin validar el rango (camino feliz).
Ejercicio 9.5 (con Scanner). Reescribe el ejercicio 9.2 usando Scanner.nextDouble() con useLocale(Locale.US). Compara cuál te resulta más cómodo.
Resumen de la sección 9
java.lang.IO(JEP 512, Java 25) es la forma moderna de leer y escribir por consola:IO.println,IO.print,IO.readln(),IO.readln(prompt). Al estar enjava.lang, no requiereimport.IO.readlnsiempre devuelveString. Para obtener un número, convierte conInteger.parseIntoDouble.parseDouble(Sección 8).Integer.parseIntes estricto: solo admite dígitos (y signo). Cualquier otra cosa lanzaNumberFormatException.Double.parseDoubleespera el punto como separador decimal. Si el usuario escribe coma, conviértela antes:s.replace(",", ".").Scanneres la alternativa clásica:nextInt(),nextDouble(),nextLine(). Combina lectura y conversión pero tiene trampas de locale y de buffer.- Si mezclas
nextIntconnextLineenScanner, llama a unnextLine()"basura" después del número para consumir el salto.
Lo que verás en UD3 Sección 8.
try-catch-finally,try-with-resources, excepciones propias. Aprenderás a pedir un dato al usuario y, si lo escribe mal, mostrar un mensaje y volver a pedirlo sin que el programa reviente. Es el patrón estándar para entrada robusta en cualquier aplicación.