DEV Community

Cover image for Why nextLine() Reads an Empty String After nextInt() in Java?
Aditya Sinha
Aditya Sinha

Posted on

Why nextLine() Reads an Empty String After nextInt() in Java?

Almost every Java learner encounters this problem at some point.

You write a simple program that asks for an age (int) and then a name (String). You run it, type an age, press Enter, and the program appears to skip the name input entirely.

It feels like a glitch.

But in reality, you have encountered what developers call the Scanner buffer issue. To keep things simple for beginners, I like to call it the nextLine() issue.


The Problem

Code That “Should” Work

Take a look at this snippet:

Scanner sc = new Scanner(System.in);

System.out.println("Enter an age");
int age = sc.nextInt();
// Example input: 25

System.out.println("Enter a name");
String name = sc.nextLine();
// Example input: Ahi

System.out.println("Name: " + name);
System.out.println("Age: " + age);
Enter fullscreen mode Exit fullscreen mode

You might expect the following interaction:

Enter an age
25
Enter a name
Ahi
Enter fullscreen mode Exit fullscreen mode

Sadly, it is not that simple.

When you type 25 and press Enter, the program finishes before you can even type the name. Therefore, the actual output is:

Name:
Age: 25
Enter fullscreen mode Exit fullscreen mode

Why did this happen? Let’s investigate.

Important note:
I’ve included a quick glossary at the bottom to help you with unfamiliar terms.


Investigation

What Happens Inside?

When you use the Scanner class to read input from the keyboard, every key you press is first stored inside the input buffer as a character.

The characters remain in the buffer until:

  • The program consumes them (that is, takes them out of the buffer) using methods like next(), nextInt(), nextLine(), or
  • The program terminates.

The Scanner class reads input using two strategies:

  • Token-based parsing
  • Line-based parsing

Every character inside the buffer is examined one by one.

Depending on the parsing rules being applied, a character will either be:

  • Consumed and returned (removed from the buffer and included in the result)
  • Consumed and discarded (removed from the buffer but not returned as part of the result)
  • Left in the buffer (to be processed later)


Token-Based Parsing

In this approach, input is divided into tokens and one token is returned at a time.

Rules

  • Leading delimiters are consumed and discarded.
  • From the first non-delimiter character, characters are consumed until a delimiter is detected.
  • The detected delimiter is left in the buffer.
  • The consumed characters are returned to the program as one token.

Methods That Use This Approach

  • next()
  • nextInt()
  • nextDouble()
  • nextFloat()
  • nextLong()
  • nextBoolean()


Line-Based Parsing

In this approach, input is read as an entire line.

Rules

  • Characters are consumed continuously, including whitespace characters (spaces and tabs).
  • Reading continues until a line terminator ('\n') is encountered.
  • The line terminator is consumed and discarded.
  • All characters before the line terminator are returned as a single String.

Method That Uses This Approach

  • nextLine()


Observation: Understanding the Behaviour

Now that we understand how input is read, let us trace the execution of our “failing” code to identify where things went wrong.


Step 1: Input Entry

When the program runs, the terminal displays:

Enter an age
Enter fullscreen mode Exit fullscreen mode

You type:

25
Enter fullscreen mode Exit fullscreen mode

Buffer status:

['2'] ['5'] ['\n']
Enter fullscreen mode Exit fullscreen mode

Step 2: nextInt() Executes

int age = sc.nextInt();
Enter fullscreen mode Exit fullscreen mode

Following the rules of token-based parsing, nextInt():

  • Begins reading from the buffer
  • Consumes '2' and '5' (non-delimiter characters)
  • Encounters '\n', which is a delimiter
  • Stops reading but does not consume the delimiter
  • Parses the token "25" into the integer value 25
  • Returns 25 to the program
int age = 25;
Enter fullscreen mode Exit fullscreen mode

Buffer status:

['\n']
Enter fullscreen mode Exit fullscreen mode

The line feed remains in the buffer.


Step 3: Prompt Appears

The terminal now shows:

Enter an age
25
Enter a name
Enter fullscreen mode Exit fullscreen mode

Misconception: You might expect the program to pause here and wait for you to type Ahi.

Reality: The program pauses only if the buffer is empty.


Step 4: nextLine() Executes

String name = sc.nextLine();
Enter fullscreen mode Exit fullscreen mode

Following the rules of line-based parsing, nextLine():

  • Checks the buffer
  • Immediately detects '\n'
  • Consumes and discards the line feed
  • Returns everything before '\n'

There were no characters before it.

Therefore, it returns an empty string.

String name = "";
Enter fullscreen mode Exit fullscreen mode

Step 5: Final Output

System.out.println("Name: " + name);
System.out.println("Age: " + age);
Enter fullscreen mode Exit fullscreen mode

Output:

Name:
Age: 25
Enter fullscreen mode Exit fullscreen mode

Solution

Now you understand where the problem occurred and why. Let us fix it.

There are several ways to solve this.


1. The Quick Fix

Add an extra nextLine() immediately after nextInt() to clear the buffer.

System.out.println("Enter an age");
int age = sc.nextInt();

sc.nextLine(); // Consumes and discards the leftover '\n'

System.out.println("Enter a name");
String name = sc.nextLine();
Enter fullscreen mode Exit fullscreen mode

Why It Works

  • nextInt() leaves the line feed character ('\n') in the input buffer.
  • The additional nextLine() consumes that '\n' and removes it.
  • Now, when the second nextLine() executes, the buffer is clean, so the program waits for your name input.

2. The Professional Approach

Avoid mixing token-based and line-based parsing.

Instead, read all input using nextLine() and convert numeric values explicitly using parsing methods such as Integer.parseInt().

This method takes a numeric string (for example, "25") and converts it into a primitive int value (25).

System.out.println("Enter an age:");
int age = Integer.parseInt(sc.nextLine());

System.out.println("Enter a name:");
String name = sc.nextLine();
Enter fullscreen mode Exit fullscreen mode

Why It Works

  • nextLine() consumes the line feed character each time it reads input.
  • No delimiters remain in the buffer.
  • Parsing explicitly using methods such as Integer.parseInt() gives you greater control over input handling.

Other Parsing Methods

  • Double.parseDouble()
  • Float.parseFloat()
  • Long.parseLong()
  • Boolean.parseBoolean()

3. The Duct Tape Fix

Reverse the order of the inputs.

System.out.println("Enter a name");
String name = sc.nextLine();

System.out.println("Enter an age");
int age = sc.nextInt();
Enter fullscreen mode Exit fullscreen mode

Why This Is Wrong

nextInt() still leaves '\n' in the input buffer.

If the program later requires another call to nextLine(), the same issue will immediately reappear.


Conclusion

Now you understand the whys, the hows, the dos, and the don’ts.

In Java, nothing is broken. The behaviour is defined. The rules are strict. The machine is consistent.

Use that consistency to your advantage rather than fighting against it.

Try This Yourself

Scanner sc = new Scanner(System.in);

System.out.println("Enter your full name:");
String firstName = sc.next();
String lastName = sc.next();

System.out.println("Hello " + firstName + " " + lastName);
Enter fullscreen mode Exit fullscreen mode

Input:

Aditya Sinha
Enter fullscreen mode Exit fullscreen mode

Output:

Hello Aditya Sinha
Enter fullscreen mode Exit fullscreen mode

Pause and think:

  • Why does this work?
  • How does next() decide where to stop reading?
  • What remains in the input buffer afterwards?
  • What happens if the name has more than two parts?

Glossary: Short and Simple

Buffer

When data is being transferred from a source (Point A) to a destination (Point B), it is temporarily stored in a small memory area between them called a buffer.

It serves as a waiting room for data and typically follows the FIFO (First In, First Out) principle.

Input Buffer:

  • Source: Keyboard
  • Destination: Java program

Internally, the data passes through multiple layers before reaching the Java program.


Token

A token is a continuous sequence of non-delimiter characters.

Token formation is the internal act of grouping characters together until a delimiter is found.

Example buffer:

['2']['5'][' ']['A']['h']['i']
Enter fullscreen mode Exit fullscreen mode

Tokens formed:

"25"
"Ahi"
Enter fullscreen mode Exit fullscreen mode

Parsing

When you type:

25
Enter fullscreen mode Exit fullscreen mode

Internally (represented in binary form):

'2'  -> ASCII value 50  
'5'  -> ASCII value 53  
'\n' -> ASCII value 10
Enter fullscreen mode Exit fullscreen mode

At this stage, the computer does not recognise the integer 25.
It only sees the sequence of characters '2', '5', and '\n'.

Inside nextInt():

['2','5','\n'] -> "25"
Enter fullscreen mode Exit fullscreen mode

A String token "25" is formed.

The actual parsing:

  • Checks if "25" is a valid integer
  • Converts it into the numeric value 25
"25"  -> before parsing (String)
25    -> after parsing (int)
Enter fullscreen mode Exit fullscreen mode

The integer value is then returned to the program.

Parsing here simply means converting characters into a meaningful data type.

This is different from compiler parsing, which analyses the grammatical structure of an entire program.
In both cases, however, the core idea remains the same: interpreting input according to defined rules.


Whitespace Character

A whitespace character has no visible symbol. It appears as blank space and is used to create horizontal or vertical separation between visible characters.

Examples:

  • ' ' (space)
  • '\t' (tab)
  • '\n' (line feed)
System.out.println("Name" + " " + "Age" + "\n" + "Ahi" + "\t" + "25");
Enter fullscreen mode Exit fullscreen mode

Output:

Name Age
Ahi     25
Enter fullscreen mode Exit fullscreen mode

Escape Sequence Character

An escape sequence is a special character representation used inside a string. It begins with a backslash (\).

Examples:

  • \n
  • \t
  • \"
System.out.println("He said, \"Hello!\"");
Enter fullscreen mode Exit fullscreen mode

Output:

He said, "Hello!"
Enter fullscreen mode Exit fullscreen mode

Escape sequences and whitespace characters are not the same thing.

  • \" → Escape sequence, not whitespace
  • \n → Escape sequence and whitespace
  • ' ' → Whitespace, not escape sequence

Delimiter

In the context of Scanner and input processing in Java, a delimiter is a character or pattern used to separate input into smaller pieces called tokens. It marks where one token ends and the next begins like a boundary.

By default, Scanner uses whitespace characters as delimiters.

When you type:

25 Ahi
Enter fullscreen mode Exit fullscreen mode

The space acts as a delimiter, and Scanner sees two tokens:

[25] [Ahi]
Enter fullscreen mode Exit fullscreen mode

You can even change it using useDelimiter() method:

sc.useDelimiter(",");
Enter fullscreen mode Exit fullscreen mode

Now the comma becomes the delimiter.
If the input is:

25,Ahi
Enter fullscreen mode Exit fullscreen mode

The tokens will be:

[25] [Ahi]
Enter fullscreen mode Exit fullscreen mode

Line Terminator

A line terminator is a kind of whitespace character (also an escape sequence character) that is used to move the cursor to a new line.

Examples:

  • '\n' (Line feed)
  • '\r' (Carriage return)
System.out.println("Hello\nWorld");
Enter fullscreen mode Exit fullscreen mode

Output:

Hello
World
Enter fullscreen mode Exit fullscreen mode

Top comments (0)