Java User Input
Programs often need data from the person running them. The standard way to read keyboard input in a console program is the Scanner class from java.util, which reads from System.in (standard input) and converts the text into Java types.
Reading a Line of Text
import java.util.Scanner;
public class Greet {
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 + "!");
}
}
Sample run:
Enter your name: Ada Lovelace
Hello, Ada Lovelace!
How it works
import java.util.Scanner;makes the class available.Scanneris not injava.lang, so the import is required.new Scanner(System.in)creates a scanner attached to standard input.System.inis a raw byte stream;Scanneradds parsing on top of it.System.out.print(notprintln) displays the prompt and leaves the cursor on the same line, so the user types next to it.nextLine()blocks: the program pauses until the user presses Enter. It then returns everything typed on that line, without the line terminator.
Reading Numbers and Other Types
Scanner has a method for each primitive type:
| Method | Returns | Reads |
|---|---|---|
nextLine() | String | The rest of the current line |
next() | String | The next word (up to whitespace) |
nextInt() | int | The next token as an integer |
nextLong() | long | The next token as a long |
nextDouble() | double | The next token as a double |
nextBoolean() | boolean | true or false (case-insensitive) |
Scanner sc = new Scanner(System.in);
System.out.print("Age: ");
int age = sc.nextInt();
System.out.print("Height in meters: ");
double height = sc.nextDouble();
System.out.printf("You are %d years old and %.2f m tall.%n", age, height);
Tokens versus lines
nextInt, nextDouble, and next read tokens: sequences of non-whitespace characters. Spaces, tabs, and newlines separate tokens. Several values can therefore be entered on one line:
System.out.print("Enter width and height: ");
int w = sc.nextInt();
int h = sc.nextInt();
System.out.println("Area: " + (w * h));
Enter width and height: 4 7
Area: 28
nextLine instead reads up to the end of the line, including spaces, which is why it is used for names, addresses, and sentences.
The nextInt/nextLine Problem
Mixing token methods with nextLine produces a well-known surprise:
System.out.print("Age: ");
int age = sc.nextInt();
System.out.print("Name: ");
String name = sc.nextLine(); // returns "" immediately
System.out.println(age + " / [" + name + "]");
Age: 30
Name: 30 / []
When the user types 30 and presses Enter, the input buffer contains 30\n. nextInt consumes 30 but leaves the newline. The following nextLine sees that newline at once, returns the empty text before it, and never waits for the name.
Two fixes:
// Fix 1: consume the leftover newline
int age = sc.nextInt();
sc.nextLine(); // discard rest of the line
String name = sc.nextLine();
// Fix 2: read every line as text and parse it yourself
int age = Integer.parseInt(sc.nextLine().strip());
String name = sc.nextLine();
The second approach is generally more robust, because every read consumes a whole line and the program controls the parsing.
Handling Invalid Input
If the user types abc when nextInt expects a number, it throws InputMismatchException. The invalid token remains in the buffer, so calling nextInt again throws again. Validation must discard it:
int age;
while (true) {
System.out.print("Age: ");
if (sc.hasNextInt()) {
age = sc.nextInt();
sc.nextLine(); // clear the rest of the line
if (age >= 0 && age <= 150) {
break;
}
System.out.println("Age must be between 0 and 150.");
} else {
System.out.println("Please enter a whole number.");
sc.nextLine(); // discard the invalid input
}
}
hasNextInt() checks whether the next token can be read as an int without consuming it. Every hasNextXxx method mirrors a nextXxx method. The loop repeats until the input is both a number and within range. Input validation of this kind belongs in any program that takes values from a person, since people mistype.
With the line-based approach, the same check uses try/catch:
while (true) {
System.out.print("Quantity: ");
String line = sc.nextLine().strip();
try {
int qty = Integer.parseInt(line);
if (qty > 0) {
System.out.println("Ordered " + qty);
break;
}
System.out.println("Quantity must be positive.");
} catch (NumberFormatException e) {
System.out.println("'" + line + "' is not a number.");
}
}
Reading Until the Input Ends
hasNextLine() returns false when no more input is available. This lets a program process a stream of lines, whether typed (ending with Ctrl+D on Linux/macOS or Ctrl+Z then Enter on Windows) or redirected from a file:
Scanner sc = new Scanner(System.in);
int lines = 0, words = 0;
while (sc.hasNextLine()) {
String line = sc.nextLine();
lines++;
if (!line.isBlank()) {
words += line.strip().split("\\s+").length;
}
}
System.out.println(lines + " lines, " + words + " words");
java WordCount < notes.txt
The < redirect feeds the file to standard input, so the same program works interactively and with files.
Closing the Scanner
A Scanner holds a resource and has a close() method. Closing a scanner also closes the stream it wraps, and closing System.in cannot be undone: any later attempt to read standard input, even through a new Scanner, fails with NoSuchElementException.
The usual practice is to create one Scanner for System.in, share it for the life of the program, and let the JVM release it at exit. Do not create a new scanner inside every method that needs input, and do not close one in a helper method. For scanners reading files, which should be closed, use try-with-resources (covered in the exceptions section).
Command-Line Arguments
Input can also be supplied when the program starts, through the args parameter of main:
public class Add {
public static void main(String[] args) {
if (args.length != 2) {
System.err.println("Usage: java Add <a> <b>");
System.exit(1);
}
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
System.out.println(a + b);
}
}
java Add 12 30
42
Arguments arrive as String values and must be parsed. Command-line arguments suit tools that run non-interactively, such as scripts and scheduled jobs; Scanner suits programs that converse with a user.
Practical Example: Simple Bill Splitter
import java.util.Scanner;
public class BillSplitter {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double total = readPositiveDouble(sc, "Bill total: ");
int people = (int) readPositiveDouble(sc, "Number of people: ");
double tipPercent = readPositiveDouble(sc, "Tip %: ");
double withTip = total * (1 + tipPercent / 100);
double each = withTip / people;
System.out.printf("Total with tip: %.2f%n", withTip);
System.out.printf("Each person pays: %.2f%n", each);
}
static double readPositiveDouble(Scanner sc, String prompt) {
while (true) {
System.out.print(prompt);
String line = sc.nextLine().strip();
try {
double value = Double.parseDouble(line);
if (value > 0) {
return value;
}
} catch (NumberFormatException ignored) {
}
System.out.println("Enter a number greater than 0.");
}
}
}
Sample run:
Bill total: 2400
Number of people: four
Enter a number greater than 0.
Number of people: 4
Tip %: 10
Total with tip: 2640.00
Each person pays: 660.00
All reading goes through one helper that reads a full line, parses it, checks the range, and repeats on failure. The single Scanner is passed to the helper rather than recreated. Because every read consumes a whole line, the nextInt/nextLine problem cannot occur.