Reading user input in Java
Scanner basics, nextInt vs nextLine pitfall.
Meet Scanner
Scanner wraps System.in (the keyboard) and splits typed text into tokens: chunks separated by whitespace. nextInt(), nextDouble() and next() each read one token. nextLine() reads the rest of the current line.
Scanner sc = new Scanner(System.in);
int age = sc.nextInt(); // one token
String word = sc.next(); // one word
String rest = sc.nextLine(); // rest of lineSimulated typing
A Scanner can also read from a String, handy for testing. The "user" typed 30, Enter, Ana, Enter. What prints?
Scanner sc = new Scanner("30\nAna\n");
int age = sc.nextInt();
String name = sc.nextLine();
System.out.println("[" + name + "]");[Ana][][30]
Show the answer
[], an empty string! nextInt() read the digits 30 and stopped *before* the Enter. Then nextLine() read from there to that Enter: nothing.
The leftover Enter
The input is really 30⏎Ana⏎. **nextInt() takes only the digits and leaves the newline in the buffer.** The next nextLine() happily reads "everything up to the newline", which is empty, and returns "" immediately. The user never gets to type.
// buffer: 3 0 ⏎ A n a ⏎
sc.nextInt(); // takes 3 0
sc.nextLine(); // takes up to ⏎ → ""Reading a number, then a line
int age = sc.nextInt();
String name = sc.nextLine();name is the empty rest of the number's line.
int age = sc.nextInt();
sc.nextLine(); // discard rest
String name = sc.nextLine();One extra nextLine() clears the leftover. Or read every line and parse it: Integer.parseInt(sc.nextLine()). Don't create a second Scanner on System.in: the first may already have buffered the input.
With the fix
Same input, one extra line. What prints?
Scanner sc = new Scanner("30\nAna\n");
int age = sc.nextInt();
sc.nextLine();
String name = sc.nextLine();
System.out.println(name + " is " + age);Ana is 30is 30Ana is 0
Show the answer
The extra nextLine() swallows the leftover newline, so the second nextLine() reads the real line: Ana.
Letters where a number should be
If the user types abc and you call nextInt(), Scanner throws **InputMismatchException** and leaves abc unread. Peek first with **hasNextInt()**: it checks whether an int comes next *without reading it*.
if (sc.hasNextInt()) {
int n = sc.nextInt();
} else {
sc.next(); // discard the bad token
}Java 25's shortcut
Java 25 finalized the **IO** class in java.lang. IO.readln("Name: ") prints the prompt and returns the whole line the user types: no Scanner, no leftover newlines. IO.println and IO.print write output.
String name = IO.readln("Name: ");
int age = Integer.parseInt(
IO.readln("Age: "));
IO.println("Hi " + name);In real projects
The nextInt()/nextLine() trap is a classic in coding-challenge sites and exam questions, where input arrives in exact formats. Real tools validate every input (never trust users!) and often read whole lines and parse them, which avoids the trap entirely.
Key takeaways
- Scanner sc = new Scanner(System.in); creates the reader
- nextInt() reads a number but leaves the newline in the buffer
- Fix: call an extra sc.nextLine() after nextInt(), or read lines and parse them
- Java 25 adds IO.readln("Prompt: ") for quick line input
Scanner arrived in Java 5 (2004). Before that, reading a number from the keyboard meant wrapping System.in in an InputStreamReader, then a BufferedReader, then calling Integer.parseInt.
Practice questions
The user types 30 and presses Enter. The program ends without ever waiting for a name. Why?
Scanner sc = new Scanner(System.in);
System.out.print("Age: ");
int age = sc.nextInt();
System.out.print("Name: ");
String name = sc.nextLine();- nextLine() only works before any nextInt() call
- nextInt() left the newline behind, and nextLine() read that empty rest of the line
- print() doesn't flush, so the second prompt is skipped
- Scanner closes itself after reading a number
Check your answer
nextInt() left the newline behind, and nextLine() read that empty rest of the line. After nextInt() reads 30, the input still holds the newline. nextLine() reads up to that newline and returns an empty string immediately.
What's the best fix for the skipped name in the previous program?
- Replace nextLine() with nextInt()
- Create a second Scanner for the name
- Call sc.nextLine() once right after nextInt() to consume the leftover newline
- Add Thread.sleep(1000) before reading the name
Check your answer
Call sc.nextLine() once right after nextInt() to consume the leftover newline. One extra nextLine() discards the rest of the number's line. A second Scanner on System.in is a bad idea: the first one may already have buffered the input.