Home Java Java Scanner Class Explained — Read Input Like a Pro (With Real Examples)

Java Scanner Class Explained — Read Input Like a Pro (With Real Examples)

In Plain English 🔥
Imagine a cashier at a supermarket. Your program is the cashier, and Scanner is the little device that reads the barcode when you slide an item across it. Without it, the cashier has no way to know what item just arrived. Scanner is Java's built-in 'reading device' — it picks up text typed on a keyboard (or written in a file) and hands it to your program so your code can actually do something with it. No Scanner, no input. It's that simple.
⚡ Quick Answer
Imagine a cashier at a supermarket. Your program is the cashier, and Scanner is the little device that reads the barcode when you slide an item across it. Without it, the cashier has no way to know what item just arrived. Scanner is Java's built-in 'reading device' — it picks up text typed on a keyboard (or written in a file) and hands it to your program so your code can actually do something with it. No Scanner, no input. It's that simple.

Every useful program in the real world needs to talk to a human. A login screen needs a username. A calculator needs two numbers. A quiz app needs an answer. Without the ability to read what a user types, your Java program is essentially a locked room — it can think, but it can't listen. That's where the Scanner class steps in, and it's one of the very first things every Java developer learns for exactly that reason.

Before Scanner existed, reading input from a keyboard in Java was genuinely painful. You had to work with low-level streams, wrap them in readers, and handle checked exceptions just to read a single number. Scanner wraps all of that complexity in a clean, beginner-friendly API. You get methods like nextLine(), nextInt(), and nextDouble() that read exactly the type of data you want — no ceremony required.

By the end of this article you'll know how to set up a Scanner, read strings and numbers from the keyboard, read input from a file, close the Scanner correctly, and — critically — avoid the two nasty bugs that trip up almost every beginner. You'll also have three fully runnable programs you can copy, run, and tweak right now.

What Is Scanner and How Do You Set It Up?

Scanner lives in the java.util package, which means you need to import it before you can use it. Think of an import like telling your kitchen which cookbook to pull off the shelf — you're telling Java 'I need the Scanner recipe from the java.util cookbook'.

Once imported, you create a Scanner object. An object is just a working instance of a class — like printing a specific form from a template. You hand the Scanner constructor a source to read from. The most common source is System.in, which represents the keyboard. Literally: System.in means 'standard input', which is the stream of characters that flows in when a user types.

The Scanner then sits and waits. When your code calls a method like nextLine(), the program pauses, a cursor blinks in the terminal, the user types something and hits Enter, and Scanner captures everything typed before that Enter key.

One important habit to build immediately: always close your Scanner when you're done with it. A Scanner holds a connection to its source (keyboard or file). Leaving it open is like leaving a tap running — it wastes resources and can cause subtle bugs in larger programs.

GreetUser.java · JAVA
12345678910111213141516171819202122
import java.util.Scanner; // Step 1: import Scanner from the java.util package

public class GreetUser {

    public static void main(String[] args) {

        // Step 2: create a Scanner object connected to the keyboard (System.in)
        Scanner keyboardReader = new Scanner(System.in);

        // Step 3: prompt the user so they know what to type
        System.out.print("Enter your name: ");

        // Step 4: read the entire line the user types (including spaces)
        String userName = keyboardReader.nextLine();

        // Step 5: use the input — here we just greet the user
        System.out.println("Hello, " + userName + "! Welcome to TheCodeForge.");

        // Step 6: always close the Scanner when you're finished reading
        keyboardReader.close();
    }
}
▶ Output
Enter your name: Sarah
Hello, Sarah! Welcome to TheCodeForge.
🔥
Why System.in?System.in is Java's built-in handle to whatever is connected to standard input — usually the keyboard in a terminal. When you write new Scanner(System.in) you're saying 'watch the keyboard and give me what the user types'. Later you'll see you can swap System.in for a File object and Scanner will read a text file in exactly the same way.

Reading Different Data Types — Strings, Integers and Decimals

Scanner doesn't just read raw text. It can parse that text directly into the Java data type you need — int, double, boolean, and more. Each data type has its own dedicated method, and choosing the right one saves you from having to convert strings manually.

nextLine() reads an entire line of text up to (but not including) the newline character created by pressing Enter. It returns a String.

next() reads a single 'token' — one word, stopping at whitespace. Useful for reading one word at a time.

nextInt() reads the next token and tries to parse it as a whole number (int). If the user types '42', you get the integer 42, ready for arithmetic.

nextDouble() does the same for decimal numbers. The user types '3.14' and you get a double you can multiply, divide, or compare.

The program below builds a simple age-and-height form. Notice how we mix data types in one conversation — that's exactly what real programs do.

UserProfileForm.java · JAVA
123456789101112131415161718192021222324252627282930313233343536
import java.util.Scanner;

public class UserProfileForm {

    public static void main(String[] args) {

        Scanner inputReader = new Scanner(System.in);

        // --- Read a String ---
        System.out.print("What is your full name? ");
        String fullName = inputReader.nextLine(); // reads the whole line, spaces included

        // --- Read an integer ---
        System.out.print("How old are you? ");
        int age = inputReader.nextInt(); // parses the typed text directly into an int

        // --- Read a double ---
        System.out.print("What is your height in metres? ");
        double heightInMetres = inputReader.nextDouble(); // parses into a decimal number

        // --- Display a summary ---
        System.out.println("\n--- Profile Summary ---");
        System.out.println("Name   : " + fullName);
        System.out.println("Age    : " + age + " years");
        System.out.printf("Height : %.2f m%n", heightInMetres); // %.2f = 2 decimal places

        // Calculate something real with the input
        if (age >= 18) {
            System.out.println("Status : Adult");
        } else {
            System.out.println("Status : Minor");
        }

        inputReader.close();
    }
}
▶ Output
What is your full name? Maria Gonzalez
How old are you? 24
What is your height in metres? 1.68

--- Profile Summary ---
Name : Maria Gonzalez
Age : 24 years
Height : 1.68 m
Status : Adult
⚠️
Watch Out: The nextInt() + nextLine() TrapWhen you call nextInt() and then nextLine() right after it, nextLine() reads the leftover newline character from when the user pressed Enter after typing the number — so it returns an empty string instead of the next line of text. The fix is to add an extra inputReader.nextLine() call immediately after nextInt() to consume that leftover newline before you read your actual string. This is covered in detail in the Common Mistakes section below.

Reading Input From a File — Same Tool, Different Source

Here's something that surprises many beginners: Scanner isn't just for keyboards. Because it accepts any source that Java can read from, you can point it at a text file and it reads line by line (or token by token) in exactly the same way. This is genuinely powerful — learn Scanner once, use it two ways.

To read from a file, you create a File object pointing at the file path, then pass that File object to the Scanner constructor instead of System.in. The rest of the API — nextLine(), nextInt(), hasNextLine() — works identically.

hasNextLine() is your best friend when reading files. It returns true as long as there are more lines to read, which makes it a perfect condition for a while loop. Without it you'd have to know in advance how many lines the file has.

Note that opening a file can fail (file not found, permission denied), so Java forces you to handle a FileNotFoundException. We use a try-with-resources block below, which is the modern, correct approach — it automatically closes the Scanner when the block ends, even if an exception occurs.

FileLineReader.java · JAVA
123456789101112131415161718192021222324252627282930313233343536
import java.util.Scanner;
import java.io.File;             // needed to represent the file on disk
import java.io.FileNotFoundException; // thrown if the file doesn't exist

public class FileLineReader {

    public static void main(String[] args) {

        // Imagine scores.txt contains:
        // Alice 95
        // Bob 87
        // Carol 92

        File scoresFile = new File("scores.txt"); // point to the file

        // try-with-resources: Scanner is automatically closed when the block ends
        try (Scanner fileScanner = new Scanner(scoresFile)) {

            int lineNumber = 1;

            // hasNextLine() returns true if there is another line to read
            while (fileScanner.hasNextLine()) {

                String currentLine = fileScanner.nextLine(); // read one full line
                System.out.println("Line " + lineNumber + ": " + currentLine);
                lineNumber++;
            }

            System.out.println("\nFinished reading " + (lineNumber - 1) + " lines.");

        } catch (FileNotFoundException exception) {
            // This runs if scores.txt doesn't exist in the project directory
            System.out.println("Error: File not found — " + exception.getMessage());
        }
    }
}
▶ Output
Line 1: Alice 95
Line 2: Bob 87
Line 3: Carol 92

Finished reading 3 lines.
⚠️
Pro Tip: Use try-with-resources Every TimeThe try-with-resources syntax (try (Scanner s = new Scanner(...)) { ... }) guarantees the Scanner is closed the moment the block ends — whether it exits normally or throws an exception. This is cleaner and safer than manually calling close() in a finally block, and it's the pattern you'll see in all modern Java codebases.

Validating Input in a Loop — Building a Bulletproof Input Reader

Real programs can't trust users to type perfectly. Someone will type 'abc' when you asked for a number. If nextInt() gets a non-numeric token it throws an InputMismatchException and crashes your program. That's a terrible user experience.

The professional solution is to validate input inside a loop. Scanner's hasNextInt() method (and its siblings hasNextDouble(), hasNextLong()) lets you check whether the next token is actually parseable as that type — before you try to parse it. Think of it as asking 'is the next thing in the queue actually a number?' before reaching in to grab it.

The loop below keeps asking until the user provides a valid positive integer. Notice two things: we call next() to consume the bad token when validation fails (otherwise Scanner is stuck on the same bad input forever), and we give the user a clear error message so they understand what went wrong.

SafeAgeInput.java · JAVA
12345678910111213141516171819202122232425262728293031323334
import java.util.Scanner;

public class SafeAgeInput {

    public static void main(String[] args) {

        Scanner console = new Scanner(System.in);
        int userAge = -1; // sentinel value: -1 means 'not yet set'

        // Keep looping until we have a valid age
        while (userAge < 0 || userAge > 130) {

            System.out.print("Please enter your age (0–130): ");

            if (console.hasNextInt()) { // check BEFORE parsing — safe!

                userAge = console.nextInt();

                if (userAge < 0 || userAge > 130) {
                    // The input was an integer but outside our acceptable range
                    System.out.println("That age isn't realistic. Try again.");
                }

            } else {
                // The input wasn't an integer at all (e.g., the user typed 'hello')
                String badInput = console.next(); // MUST consume the bad token or we loop forever
                System.out.println("'" + badInput + "' is not a number. Please type digits only.");
            }
        }

        System.out.println("Great — you are " + userAge + " years old.");
        console.close();
    }
}
▶ Output
Please enter your age (0–130): hello
'hello' is not a number. Please type digits only.
Please enter your age (0–130): -5
That age isn't realistic. Try again.
Please enter your age (0–130): 27
Great — you are 27 years old.
🔥
Interview Gold: hasNextInt() vs nextInt()Interviewers love asking why you'd use hasNextInt() before nextInt(). The answer: nextInt() throws InputMismatchException if the token isn't an integer, which crashes the program. hasNextInt() is a non-destructive peek — it checks without consuming the token, so you can branch safely. This shows you understand defensive programming, not just happy-path coding.
Scanner MethodWhat It ReadsReturnsStops At
nextLine()Everything up to Enter keyString (can contain spaces)Newline character \n
next()One word / tokenString (no spaces)Any whitespace
nextInt()Next token as a whole numberintWhitespace (leaves \n behind)
nextDouble()Next token as a decimaldoubleWhitespace (leaves \n behind)
nextBoolean()Next token as true/falsebooleanWhitespace
hasNextLine()Does another line exist?boolean (true/false)Does not consume input
hasNextInt()Is the next token an int?boolean (true/false)Does not consume input

🎯 Key Takeaways

  • Scanner is a wrapper around any readable source — swap System.in for a File object and the entire API works identically, which means one skill covers two common use cases.
  • nextInt(), nextDouble() and friends leave the newline character in the buffer — always consume it with an extra nextLine() before reading your next string to avoid the empty-string bug.
  • Always use hasNextInt() (or hasNextDouble()) to validate input before parsing it — nextInt() on bad input throws InputMismatchException and crashes; hasNextInt() peeks safely without consuming the token.
  • Create exactly one Scanner per input source and close it exactly once — multiple Scanners on System.in will cause NoSuchElementException; use try-with-resources for file Scanners to guarantee cleanup even if an exception occurs.

⚠ Common Mistakes to Avoid

  • Mistake 1: Calling nextLine() right after nextInt() returns an empty string — When nextInt() reads a number, it leaves the newline character (\n from pressing Enter) sitting in the input buffer. The very next nextLine() call reads that leftover newline and returns an empty string, completely skipping the user's actual next input. Fix: add an extra inputReader.nextLine() call immediately after nextInt() (or nextDouble()) to flush that leftover newline before you read your real string data.
  • Mistake 2: Forgetting to consume the bad token inside a hasNextInt() validation loop — If the user types a non-integer and you call next() to reject it but forget to actually call next() to remove it from the buffer, Scanner is stuck reading the same bad token on every loop iteration. The loop spins forever printing the same error. Fix: always call console.next() (assigning it to a variable is optional but good practice) inside the else branch to discard the invalid input before looping back.
  • Mistake 3: Creating multiple Scanner objects pointing to System.in — Beginners sometimes create a new Scanner(System.in) in multiple methods or classes. Closing one of them also closes System.in itself, making all other Scanners unusable and throwing a NoSuchElementException. Fix: create one Scanner object, pass it around as a method parameter or store it in a shared location, and close it exactly once when the entire program is done reading input.

Interview Questions on This Topic

  • QWhat is the difference between next() and nextLine() in Java's Scanner class, and when would you choose one over the other?
  • QWhy does calling nextLine() immediately after nextInt() sometimes return an empty string, and how do you fix it?
  • QIf you need to read from both the keyboard and a file in the same program, how would you structure your Scanner usage to avoid resource leaks?

Frequently Asked Questions

Do I need to close the Scanner after using it?

Yes, you should always close a Scanner when you're finished with it. An unclosed Scanner holds an open connection to its source (keyboard or file), which wastes system resources. For file Scanners, use try-with-resources to close automatically. For System.in, call close() at the end of your program — but be aware that closing it also closes System.in itself, so only do it once.

What is the difference between Scanner and BufferedReader in Java?

Scanner is easier to use for beginners because it parses data types directly (nextInt(), nextDouble(), etc.) and works with multiple sources including keyboards and files. BufferedReader is faster and better for reading large files line by line, but it only returns Strings — you have to parse types manually. For most beginner and intermediate programs, Scanner is the right choice. Switch to BufferedReader when performance with large files becomes a concern.

Why does my Scanner program skip a line of input without waiting for me to type?

This is almost certainly the nextInt()-then-nextLine() bug. When you read a number with nextInt(), it consumes the digits but leaves the Enter key's newline character in the input buffer. The immediately following nextLine() reads that leftover newline and returns instantly with an empty string. Fix it by adding an extra scanner.nextLine() call right after nextInt() to discard the leftover newline before you read your actual string.

🔥
TheCodeForge Editorial Team Verified Author

Written and reviewed by senior developers with real-world experience across enterprise, startup and open-source projects. Every article on TheCodeForge is written to be clear, accurate and genuinely useful — not just SEO filler.

← PreviousJava Modules — JPMSNext →Java PrintWriter and PrintStream
Forged with 🔥 at TheCodeForge.io — Where Developers Are Forged