Java's Scanner.nextLine() is being skipped

Java’s Scanner nextLine() call is being skipped

As a programming language with its fair share of quirks, one of the many things a new Java programmer will run into is the issue of their Scanner.nextLine() calls being ignored. Consider the following Java code:

JavaNextLineProblem.java

import java.util.Scanner;
public class JavaNextLineProblem {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);

		// Prompt the user to enter their name.
		System.out.print("Enter your name: ");
		String name = input.nextLine();

		// Prompt the user to enter their age.
		System.out.print("Enter your age: ");
		int age = input.nextInt();

		// Prompt the user to enter a description.
		System.out.print("Describe yourself in a sentence: ");
		String description = input.nextLine();

		// Prompt the user to enter a message.
		System.out.print("Enter a message: ");
		String message = input.nextLine();
	}
}

This is the desired result (user input coloured in green):

Enter your name: John
Enter your age: 21
Describe yourself in a sentence: I am awesome.
Enter a message: Hello world!

However, this is what you actually get:

Enter your name: John
Enter your age: 21
Describe yourself in a sentence: Enter a message: Hello world!

The program skips over the collection of input for the Describe yourself in a sentence prompt, and goes straight into collecting the input for the Enter a message prompt. What’s going on?

Why does this happen?

If you’ll like to get right to the answer, you can skip through this section to the next one.

To understand why this happens, we first have to understand how the nextLine() method works. When it is called on a Scanner that is reading from Java’s System.in (i.e. a Scanner created using new Scanner(System.in), as in our code above), nextLine() will wait until it can read a newline character from the input stream. Once there is a newline character (i.e. due to the user pressing Enter), nextLine() will retrieve all the characters that are before the newline, and consume the newline itself.

The way that nextLine() captures input can make for some very odd behaviour when you are also collecting input using other Scanner functions like nextInt() or nextDouble(), because these other functions do not consume newlines.

Take, for example, the following sequence where the player is prompted to input their age. The age is retrieved using nextInt() (highlighted in yellow below), and the newline character (represented below with ⏎ and highlighted in red) is left unconsumed:

Enter your age: 21

Recall that right after prompting for the user’s age, the program prompts the user to enter a description for themselves and collects the input with nextLine():

// Prompt the user to enter their age.
System.out.print("Enter your age: ");
int age = input.nextInt();

// Prompt the user to enter a description.
System.out.print("Describe yourself in a sentence: ");
String description = input.nextLine();

As there is an unconsumed newline at the end of the integer input, however, the subsequent nextLine() call immediately consumes the remaining newline character instead of waiting for more user input. This is why the attempt to assign the description variable in the code above doesn’t seem to work.


Article continues after the advertisement:


How to fix the issue

The fix is simple: add an extra call to nextLine() whenever you are using nextLine() to retrieve strings after prior calls to any of the other next functions (like nextInt(), nextDouble(), nextChar(), etc.).

In our case, here is the fix:

// Prompt the user to enter their age.
System.out.print("Enter your age: ");
int age = input.nextInt();

input.nextLine(); // Consumes the newline character that is left behind.

// Prompt the user to enter a description.
System.out.print("Describe yourself in a sentence: ");
String description = input.nextLine();

Note that you do not have to call nextLine() after every call of a next function. Consider the following example:

// Prompt the user to enter their age.
System.out.print("Enter your age: ");
int age = input.nextInt();

// Prompt the user to enter their ID number.
System.out.print("Enter your ID number: ");
int id = input.nextInt();

input.nextLine(); // Consumes the newline character that is left behind.

// Prompt the user to enter a description.
System.out.print("Describe yourself in a sentence: ");
String description = input.nextLine();

In the example above, the 2nd call to nextInt() consumes all characters between the 2 integer inputs, including the newline input. Hence, you only have to include the extra call to nextLine() after the last nextInt() call, and before your actual nextLine() call.

Conclusion

I hoped that this short article was what you were looking for, and helped you fix your problem! Do leave us a comment if you find any mistakes in our article, so that we can make it better for future readers.

Leave a Reply

Your email address will not be published.