Reading Input with Scanner
A program that always prints the same thing is not very interesting. Scanner is the standard way a beginner reads what the user types. It lives in the java.util package, so you need import java.util.Scanner; at the top of the file — a missing import is the reason for cannot find symbol: class Scanner, not a spelling mistake.
You create one by wrapping System.in, the stream connected to the keyboard: Scanner sc = new Scanner(System.in);. From there you call a method named after the type you want. nextLine() reads everything up to the end of the line, including spaces. next() reads one word, stopping at the first space. nextInt(), nextDouble(), nextLong() and nextBoolean() read and convert a single value of that type.
Use System.out.print rather than println for the prompt, so the cursor stays on the same line as the question. It is a small thing that makes a console program feel finished.
Understanding how Scanner sees the input explains everything that goes wrong later. It does not read "a number" or "a line" from the keyboard directly; it reads from a stream of characters and consumes only as much as the method it was asked for needs. Whatever it does not consume — including the invisible newline character produced when the user presses Enter — stays in the stream waiting for the next call.
import java.util.Scanner;
public class InputExample {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = sc.nextLine(); // whole line, spaces included
System.out.print("Enter your city: ");
String city = sc.next(); // ONE word only
System.out.print("Enter your age: ");
int age = sc.nextInt();
System.out.print("Enter your percentage: ");
double pct = sc.nextDouble();
System.out.printf("%s from %s, age %d, scored %.2f%%%n",
name, city, age, pct);
}
}
// Enter your name: Ananya Sharma
// Enter your city: Pune
// Enter your age: 20
// Enter your percentage: 87.5
// Ananya Sharma from Pune, age 20, scored 87.50% - Create one Scanner on
System.infor the whole program and pass it around if you need it in several methods. Creating a second one while the first is still open leads to input mysteriously disappearing, because each buffers characters independently.
The nextInt-then-nextLine Trap
This is the bug every Java learner hits in their first week, and it looks like the program is skipping a question entirely.
You ask for a number with nextInt(), then ask for a name with nextLine(). The program prints the second prompt and immediately moves on without waiting. The name variable ends up as an empty string.
Here is exactly why. When the user types 20 and presses Enter, the stream contains 20\n. nextInt() takes the digits and stops — it has what it needs, so it leaves the \n sitting there. The following nextLine() asks for "everything up to the end of the current line", finds the leftover newline immediately, and correctly returns the empty string between the number and that newline. Scanner did the right thing; the expectation was wrong.
There are two clean fixes. The quick one is to call an extra sc.nextLine() after every numeric read, purely to swallow the leftover newline. The more robust one, and the one professionals prefer, is to never mix the two styles: read every input with nextLine() and convert to numbers yourself with Integer.parseInt() or Double.parseDouble(). That way nothing is ever left behind, and it makes error handling easier too.
import java.util.Scanner;
public class TheTrap {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Age: ");
int age = sc.nextInt(); // consumes "20", leaves "\n"
System.out.print("Name: ");
String name = sc.nextLine(); // gets "" instantly — looks skipped!
System.out.println("[" + name + "]"); // []
}
}
// ---- Fix 1: swallow the leftover newline ----
int age2 = sc.nextInt();
sc.nextLine(); // discard the rest of that line
String name2 = sc.nextLine(); // now works
// ---- Fix 2 (preferred): read lines only, convert yourself ----
System.out.print("Age: ");
int age3 = Integer.parseInt(sc.nextLine().strip());
System.out.print("Name: ");
String name3 = sc.nextLine(); - The same trap appears with
next()followed bynextLine(), and withnextDouble()followed bynextLine(). Any token-based read leaves the newline behind; onlynextLine()consumes it.
When the User Types Something Unexpected
Real users mistype. If your code calls nextInt() and the user types twenty, Scanner throws InputMismatchException and your program stops with a stack trace. In a college demo that is embarrassing; in an assignment it costs marks.
There is a second, worse version of this. If you wrap the read in a while loop to ask again, the bad token is still sitting in the stream — an exception does not consume it. Your loop reads it again, throws again, reads it again, and spins forever, printing the prompt thousands of times a second. Fixing this requires explicitly discarding the offending input with a nextLine() inside the catch block.
The tidier approach is to look before you leap. hasNextInt() asks whether the next token can be read as an int, without consuming anything and without throwing. A short loop around it gives you a program that politely re-asks until the input is valid.
If you use the read-lines-and-parse style from the previous section, the failure arrives as NumberFormatException from Integer.parseInt instead, which is easier to handle because the offending line has already been consumed. That is a real argument in its favour.
import java.util.Scanner;
public class SafeInput {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// ---- Look before you leap ----
System.out.print("Enter your age: ");
while (!sc.hasNextInt()) {
System.out.print("That is not a whole number. Try again: ");
sc.next(); // discard the bad token
}
int age = sc.nextInt();
System.out.println("Age accepted: " + age);
// ---- Or read the line and parse it ----
sc.nextLine(); // clear the leftover newline
int marks;
while (true) {
System.out.print("Enter marks: ");
try {
marks = Integer.parseInt(sc.nextLine().strip());
break;
} catch (NumberFormatException e) {
System.out.println("Please type digits only.");
}
}
System.out.println("Marks accepted: " + marks);
}
} - Do not call
sc.close()on a Scanner wrappingSystem.inunless the program is about to end. Closing the Scanner closesSystem.initself, and it cannot be reopened — every later read throwsNoSuchElementException. Some editors warn about the unclosed resource; forSystem.inspecifically, that warning is safe to ignore.
Output: print, println and printf
Java gives you three ways to write to the console and they differ in one respect each. println prints its argument and moves to a new line. print prints and stays on the same line — use it for prompts and for building a line piece by piece. printf takes a format string with placeholders and fills them in, which is how you control decimal places and column widths.
Prefer printf whenever numbers are involved. System.out.println("Total: " + 4500.5) prints Total: 4500.5, but a bill should read 4500.50, and %.2f gives you that in one step. It also rounds rather than truncating, so %.2f on 3.14159 prints 3.14 and on 2.567 prints 2.57.
Width and alignment turn a jumble of values into a readable table. A number between the % and the letter sets the minimum width — %10s right-aligns in ten columns, and a minus sign as in %-10s left-aligns instead. This is how you print a marksheet that lines up.
Use %n rather than \n inside a format string. %n emits whatever line separator the current operating system uses, so a file your program writes opens correctly on Windows as well as Linux.
// The three forms
System.out.println("Ends with a newline");
System.out.print("Stays ");
System.out.print("on one line");
System.out.println(); // just a line break
System.out.printf("Name: %s, Marks: %d%n", "Ananya", 87);
// Controlling decimals
double fee = 4500.5;
System.out.println("Total: " + fee); // Total: 4500.5
System.out.printf("Total: %.2f%n", fee); // Total: 4500.50
System.out.printf("Rounded: %.2f%n", 2.567); // Rounded: 2.57
// A table that lines up
String[] names = {"Ananya", "Rahul", "Meera"};
int[] scores = {87, 92, 78};
System.out.printf("%-10s %5s%n", "NAME", "MARKS");
for (int i = 0; i < names.length; i++) {
System.out.printf("%-10s %5d%n", names[i], scores[i]);
}
// NAME MARKS
// Ananya 87
// Rahul 92
// Meera 78
// Errors go to a separate stream
System.err.println("Something went wrong"); %s— any value as text; safe when you are unsure of the type%d— a whole number (int,long); passing a double here throws at run time%f— a decimal;%.2ffixes it to two places%b—trueorfalse;%c— a single character%10s— right-align in 10 columns;%-10s— left-align%05d— pad a number with leading zeros to five digits%%— a literal percent sign;%n— a platform-correct line break
- For competitive programming and for reading very large inputs,
Scanneris noticeably slow because it parses with regular expressions.BufferedReaderwrapped aroundnew InputStreamReader(System.in)is far faster: it returns raw lines you split and parse yourself, and itsreadLine()declaresIOException, so it needs athrowsclause or a try-catch. Learn Scanner first; switch when the time limit demands it.
