Have you ever tried making a Java program that asks the user for input, only for it to crash, skip entries, or behave unpredictably? If so, you’re not alone.
Handling user input in Java seems simple but often leads to frustrating bugs if you don’t know the right approach. Maybe your program asks for a number but crashes when someone enters text, or it skips a question entirely.
That’s where Scanner
comes in. It’s Java’s easiest way to read user input - but only if you use it correctly.
In this guide, I’ll break it all down and show you how to avoid common pitfalls so that by the time you finish reading, you’ll be able to use this tool with your own projects.
Let’s dive in…
Sidenote: If you find that you’re struggling with the topics in this guide, or perhaps feel that you could use some more training, or simply want to build some more impressive projects for your portfolio, then check out my Java programming bootcamp:
Updated for 2025, you'll learn Java programming fundamentals all the way from complete beginner to advanced skills.
Better still, you’ll be able to reinforce your learning with over 80 exercises and 18 quizzes. This is the only course you need to go from complete programming beginner to being able to get hired as a Backend Developer!
With that out of the way, let’s get into this 5-minute tutorial…
When writing Java programs, you often need a way to accept user input. Maybe you’re building a calculator that requires numbers, a quiz that takes answers, or a login system that asks for a username and password.
Without input handling, Java programs are limited to hardcoded values.
For example
Imagine writing a program that asks for a user's name. Without input handling, you'd have to hardcode the name inside the program like so:
public class Main {
public static void main(String[] args) {
String name = "Alice"; // Hardcoded name
System.out.println("Hello, " + name + "!");
}
}
Sure it works, but every time you run this program, it will always print "Hello, Alice!"
. Obviously this is not great if you wanted to greet someone else, as you’d have to manually change "Alice"
in the code and recompile the program, which is not at all practical.
Scanner
solves this by allowing users to interact with the program at runtime and use their response dynamically instead.
For example
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.nextLine();
System.out.println("Hello, " + name + "!");
}
}
When this program runs, it will pause and wait for the user to type their name. Once they press Enter, the program will greet them personally—no hardcoded values needed.
Let’s take a look at this code so we can understand how it works, step by step:
Scanner scanner = new Scanner(System.in);
→ Creates a Scanner
object linked to the keyboard (System.in
)System.out.print("Enter your name: ");
→ Displays a message asking the user for inputString name = scanner.nextLine();
→ Reads an entire line of text from the userSystem.out.println("Hello, " + name + "!");
→ Prints a personalized greeting using the user’s inputSuper handy right?
So let’s show you how to set it up.
Since Scanner
isn’t automatically available in Java, the first thing you need to do is import it.
Scanner
Java organizes its built-in tools into packages, and Scanner
belongs to the java.util
package. To use it, you need to import it at the beginning of your program:
import java.util.Scanner;
This tells Java, "I want to use the Scanner
class in this program." Without this import, trying to use Scanner
would result in a compilation error.
Scanner
object (and why you need it)Once you've imported Scanner
, you need to create a Scanner
object to actually start reading input. The most common way to do this is by linking it to System.in, which represents input from the keyboard:
Scanner scanner = new Scanner(System.in);
This line creates a new Scanner
object and connects it to the keyboard, allowing your program to accept user input.
Now that Scanner is set up, let’s explore how to read different types of input correctly without running into skipped inputs or crashes.
At a high level:
next()
works finenextLine()
is the better choicenextInt()
or nextDouble()
nextBoolean()
is what you needThe trick is knowing when to use each method, because picking the wrong one can lead to skipped inputs, unexpected results, or program crashes.
Let’s go through them one by one.
User input often includes single-word responses, full names, or entire sentences. Java provides two different methods for handling this:
next()
: Reads a single word and stops at the first spacenextLine()
: Reads everything the user types until they press EnterThese two methods behave very differently, so choosing the wrong one can break your program in ways that are frustrating to debug.
For example
Let’s say you ask the user for their name and print a greeting:
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.next();
System.out.println("Hello, " + name + "!");
You run the program, they enter "John"
, and everything works as expected. But then they try to enter their full name "John Doe"
, and suddenly, only "John"
is printed.
So where did "Doe"
go?
The issue is that next()
only reads a single word and stops at the first space. This means that anything after that stays in the input buffer, waiting to be read. (If you expected "John Doe"
, but only "John"
appears, it’s because "Doe"
is still sitting there, unread).
So if you actually want the full name, nextLine()
is the better option:
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.nextLine();
System.out.println("Hello, " + name + "!");
Now, "John Doe"
is captured correctly as a single input. Huzzah!
nextLine()
instead of next()
?No, simply because next()
is still useful in certain situations:
For example
If we look at the example below, we want to read multiple values from a single line. In this case, "Alice 25"
(name and age).
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your first name and age: ");
String firstName = scanner.next();
int age = scanner.nextInt();
System.out.println(firstName + " is " + age + " years old.");
This code works because next()
reads "Alice"
, and nextInt()
reads 25
, all in one go. But if we had used nextLine()
instead, we would have to manually split the input later.
When reading numbers, Scanner
provides methods to handle both integers and floating-point values.
nextInt()
for whole numbersIf you need to read a whole number, nextInt()
is the right choice, because it ensures that only valid integers are accepted.
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your age: ");
int age = scanner.nextInt();
System.out.println("You are " + age + " years old.");
However, if the user enters letters instead of a number, the program will crash with an InputMismatchException
. (We’ll cover how to prevent this later).
nextDouble()
for decimalsSo, if you expect decimal values, like prices or weights, then nextDouble()
is a better choice.
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the price: ");
double price = scanner.nextDouble();
System.out.println("The price is $" + price);
This ensures that the user's input is recognized as a floating-point number rather than an integer.
For true/false values, nextBoolean()
reads "true"
or "false"
and automatically converts it into a boolean
.
For example
Scanner scanner = new Scanner(System.in);
System.out.print("Are you over 18? (true/false): ");
boolean isAdult = scanner.nextBoolean();
System.out.println("You answered: " + isAdult);
If the user types anything other than "true"
or "false"
, Java will throw an error. That’s why, if you’re expecting answers like "yes"
or "no"
, it’s better to read the input as a String
using nextLine()
and check the value manually.
Simple!
Using Scanner
correctly isn’t just about avoiding errors. It’s also about writing clean, maintainable, and efficient code.
With that in mind, here are some best practices to follow that will help you structure your input handling properly and avoid unnecessary issues down the line.
Scanner
instance for user inputA common mistake is creating multiple Scanner
instances for keyboard input. While it might seem harmless, doing this can cause unexpected behavior and even lead to input stream conflicts.
Bad practice
Scanner scanner1 = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner1.nextLine();
Scanner scanner2 = new Scanner(System.in);
System.out.print("Enter your age: ");
int age = scanner2.nextInt(); // Potential issues
Sure, using a single Scanner
prevents input conflicts and keeps your code cleaner. But as your program grows, having all input logic in one place can make it harder to maintain.
That’s why it’s also important to structure your code properly by keeping input handling modular.
Best practice
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.nextLine();
System.out.print("Enter your age: ");
int age = scanner.nextInt();
This makes your code cleaner and prevents input stream conflicts.
Scanner
code modular and reusableIf your program needs to take multiple inputs, avoid putting all Scanner
logic in main()
. Instead, break it into separate functions so your code is easier to read and reuse.
Bad practice
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.nextLine();
System.out.print("Enter your age: ");
int age = scanner.nextInt();
System.out.println("Hello, " + name + ". You are " + age + " years old.");
This bad practice solution works but as the program grows, it becomes harder to maintain. A better approach is to separate concerns into functions, like so:
Best practice
import java.util.Scanner;
public class UserInput {
private static Scanner scanner = new Scanner(System.in);
public static String getName() {
System.out.print("Enter your name: ");
return scanner.nextLine();
}
public static int getAge() {
System.out.print("Enter your age: ");
return scanner.nextInt();
}
public static void main(String[] args) {
String name = getName();
int age = getAge();
System.out.println("Hello, " + name + ". You are " + age + " years old.");
}
}
Structuring your code this way makes it easier to manage and scale.
But even with well-structured code, you still need to ensure users provide valid input, otherwise, your program might still crash. That’s where input validation comes in.
If you expect the user to enter numbers, it's a good idea to always assume they might enter something invalid (like letters). So instead of letting the program crash, validate input before using it.
Bad practice
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your age: ");
int age = scanner.nextInt(); // CRASHES if the user enters text
Best practice
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your age: ");
while (!scanner.hasNextInt()) {
System.out.println("Invalid input. Please enter a number.");
scanner.next(); // Discard invalid input
}
int age = scanner.nextInt();
System.out.println("You are " + age + " years old.");
Even with validation in place, handling input properly also means knowing when to close Scanner
. Closing it at the wrong time can break your program so let’s go over when to close it and when to keep it open.
Scanner
When reading from a file, you should always close Scanner
after you're done. However, it's important to remember that if you're reading from System.in
(keyboard input), closing Scanner
will close the input stream for the entire program.
So as a rule of thumb:
System.in
? Don't close it if you need more input laterBad practice
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.nextLine();
scanner.close(); // Closes System.in
System.out.print("Enter your age: ");
int age = scanner.nextInt(); // ERROR: Scanner is closed!
Best practice
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.nextLine();
// Keep scanner open if you need more input
System.out.print("Enter your age: ");
int age = scanner.nextInt();
BufferedReader
for large text processingIf your program needs to read a lot of text data, Scanner
isn’t the most efficient option. This is because it reads input one small piece at a time, which works fine for short inputs but slows things down when dealing with large files.
A better alternative is BufferedReader
, which is designed to read entire lines at once. This makes it much faster when processing large amounts of text.
For example
Let’s say you need to read a file containing thousands of customer names. Using BufferedReader
, you can read the file line by line instead of processing each word separately.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
}
}
Let’s break this down.
BufferedReader
that reads from a file named "data.txt"
line
variablewhile
loop ensures that we keep reading until there’s nothing left.If you were to use Scanner
instead, it would require extra logic to manually detect when a line ends. That’s why BufferedReader
is the better option for handling large text files efficiently.
It’s not the only time we might not use Scanner
though.
Console
is a more secure optionIf your program asks users to enter passwords or other sensitive information, Scanner
is a bad choice because it displays everything the user types, which is not ideal for security.
That’s where Console
comes in.
For example
Here’s how Console
might work in a login system:
import java.io.Console;
public class Main {
public static void main(String[] args) {
Console console = System.console();
if (console != null) {
char[] password = console.readPassword("Enter password: ");
System.out.println("Password received.");
} else {
System.out.println("Console not supported in this environment.");
}
}
}
This method keeps input hidden while typing, making it more secure than Scanner
. However, System.console()
only works when running Java from a terminal, and some IDEs such as Eclipse, may not support it.
Now that you know the best practices, let's cover all our bases and make sure you’re aware of any common issues that you might come across, their causes, and how to resolve them.
Such a rookie move but we all fall for it at some point. If you remember from earlier, Scanner
is part of the java.util
package, which means it isn’t automatically available.
So if you forget to import it, your program won’t compile, and you’ll see this error:
Main.java:3: error: cannot find symbol
Scanner scanner = new Scanner(System.in);
^
symbol: class Scanner
location: class Main
Super simple to fix - just always remember to include this line at the top of your Java file:
import java.util.Scanner;
This tells Java where to find the Scanner
class so your program can use it.
Scanner
before using itDeclaring a Scanner
variable without initializing it will cause a NullPointerException
when you try to use it.
For example
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner; // Declared but not initialized
System.out.print("Enter your name: ");
String name = scanner.nextLine(); // ERROR: scanner is not initialized!
System.out.println("Hello, " + name + "!");
}
}
How to fix it
Make sure to initialize Scanner
before using it:
Scanner scanner = new Scanner(System.in);
nextInt()
or nextDouble()
One of the most frustrating issues is when Scanner
skips input after reading a number.
For example
If you mix nextInt()
or nextDouble()
with nextLine()
, the program may skip the next text input.
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your age: ");
int age = scanner.nextInt(); // Reads the number
System.out.print("Enter your name: ");
String name = scanner.nextLine(); // Skips input!
System.out.println("Hello, " + name + "!");
Why does this happen?
This is because nextInt()
only reads the number but leaves a newline (\n
) in the input buffer. So when nextLine()
is called next, it immediately reads that leftover newline instead of waiting for user input.
The solution is to always consume the leftover newline before calling nextLine():
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your age: ");
int age = scanner.nextInt();
scanner.nextLine(); // Consume leftover newline
System.out.print("Enter your name: ");
String name = scanner.nextLine();
System.out.println("Hello, " + name + "!");
Now, nextLine()
will correctly wait for input.
InputMismatchException
when entering the wrong data typeIf the user enters text when nextInt()
or nextDouble()
expects a number, Java throws an InputMismatchException
, causing the program to crash.
For example
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your age: ");
int age = scanner.nextInt(); // CRASHES if input is not a number!
If the user types "twenty"
instead of 20
, the program crashes with this error:
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.nextInt(Unknown Source)
The solution for this is to always check if the input is valid before reading it:
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your age: ");
while (!scanner.hasNextInt()) {
System.out.println("Invalid input. Please enter a number.");
scanner.next(); // Discard invalid input
}
int age = scanner.nextInt();
System.out.println("You are " + age + " years old.");
In some regions, decimal numbers are written with a comma (1,99
) instead of a dot (1.99
).
And so if your program expects a dot but the user enters a comma, nextDouble()
will throw an error.
For example
Scanner scanner = new Scanner(System.in);
System.out.print("Enter a price: ");
double price = scanner.nextDouble(); // CRASHES if input is "1,99"
System.out.println("The price is $" + price);
The solution though is actually quite simple. If your program will be used internationally, set the locale to ensure consistent number formatting:
import java.util.Locale;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in).useLocale(Locale.US);
System.out.print("Enter a price: ");
double price = scanner.nextDouble();
System.out.println("The price is $" + price);
}
}
Now, Java will always expect decimal points (.
) instead of commas, preventing format issues.
Easy!
So as you can see, Scanner
makes it easy to handle user input in Java, but only if you use it correctly. But by following best practices and avoiding common mistakes, you’ll write input-handling code that works smoothly every time.
The best way to reinforce what you’ve learned? Try it yourself!
Go ahead and write some small programs that take different types of input: words, sentences, numbers, etc, and experiment with validation to prevent errors.
The more you practice, the more intuitive Scanner
will become. So put your knowledge to the test and start coding 😁.
Remember, if you want to fast-track your Java knowledge and get as much hands-on practice as possible, then check out my Java programming bootcamp:
Updated for 2025, you'll learn Java programming fundamentals all the way from complete beginner to advanced skills.
Better still, you’ll be able to reinforce your learning with over 80 exercises and 18 quizzes. This is the only course you need to go from complete programming beginner to being able to get hired as a Backend Developer!
Plus, once you join, you'll have the opportunity to ask questions in our private Discord community from me, other students and working DevOps professionals.