What you'll learn
A program that can't communicate isn't much use. In this module your programs start talking: printing formatted output, reading what the user types, and working with text — the most common data type you'll ever handle.
By the end you'll be able to:
- Print with
print,println, and formattedprintf - Read keyboard input with
Scannerand avoid its classic pitfall - Explain why
Stringis immutable and what that means for you - Use the essential
Stringmethods to slice, search, and transform text - Compare strings correctly with
.equals()instead of== - Use escape sequences, text blocks, and
StringBuilderfor efficient text building
Console output
You already know System.out.println(), which prints a line and moves to the next. System.out.print() is the same but without the newline, so the next output continues on the same line. For anything fancier, printf lets you build a formatted string using placeholders:
| Specifier | Means | Example |
|---|---|---|
%s | a string | printf("%s", "hi") |
%d | a whole number | printf("%d", 42) |
%f | a decimal | printf("%f", 3.14) |
%.2f | decimal, 2 places | printf("%.2f", 3.14159) |
%n | a newline | portable line break |
%% | a literal percent sign | prints % |
String name = "Sara";
int score = 95;
double gpa = 3.14159;
System.out.printf("Name: %s%n", name);
System.out.printf("Score: %d%%%n", score);
System.out.printf("GPA: %.2f%n", gpa);Reading input with Scanner
To read what the user types, Java gives you the Scanner class. You import it from java.util, wrap it around System.in (the keyboard), and call methods like nextLine(), nextInt(), and nextDouble():
import java.util.Scanner;
public class Greet {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("What's your name? ");
String name = scanner.nextLine();
System.out.print("How old are you? ");
int age = scanner.nextInt();
System.out.println("Hi " + name + ", next year you'll be " + (age + 1));
scanner.close();
}
}The nextInt() / nextLine() trap
nextInt() reads the number but leaves the Enter keystroke waiting in the buffer. A following nextLine() then reads that leftover empty line. The fix: call an extra scanner.nextLine() after nextInt() to consume it, or read everything as lines and parse with Integer.parseInt().Strings & immutability
A String is a sequence of characters — text. You create one with double quotes: "Hello". The single most important fact about strings in Java is that they are immutable: once created, a string's characters can never be changed. Every "modification" actually produces a brand-new string.
String s = "Hi";
s points to the "Hi" object.
s = s + "!";
A new object is created. The original is never modified.
Note
+ creates lots of throwaway objects. We'll fix that with StringBuilder below.Essential String methods
Because strings are objects, they come loaded with useful methods. Remember: these all return a new value rather than changing the original. Here are the ones you'll reach for daily:
| Method | What it does |
|---|---|
length() | number of characters |
charAt(i) | the character at index i (0-based) |
substring(a, b) | the slice from index a up to (not including) b |
indexOf(x) | index of the first x, or -1 if not found |
toUpperCase() / toLowerCase() | change case |
trim() / strip() | remove surrounding whitespace |
replace(a, b) | replace every a with b |
contains(x) | true if x appears inside |
split(x) | break into an array around x |
String s = " Hello, Java ";
System.out.println(s.trim()); // "Hello, Java"
System.out.println("Java".length()); // 4
System.out.println("Java".charAt(0)); // J
System.out.println("Hello".substring(1, 4)); // ell
System.out.println("banana".indexOf("na")); // 2
System.out.println("a,b,c".replace(",", "-")); // a-b-c
System.out.println("hi".toUpperCase()); // HITip
"Java", 'J' is at index 0 and 'a' (the last one) is at index 3.Comparing strings correctly
This trips up almost every beginner. To compare the text of two strings, always use .equals() — not ==. The == operator checks whether two variables point to the exact same object in memory, which is a different question entirely.
== compares identity
Are these the exact same object in memory? Rarely what you want for text.
.equals() compares content
Do these have the same characters? This is what you almost always want.
Java keeps a string pool — a cache of string literals — so identical literals often share one object and == happens to return true. That coincidence makes the bug hide until a string comes from user input or new String(), then suddenly == is false. Don't rely on it:
String a = "hello";
String b = "hello";
String c = new String("hello");
System.out.println(a == b); // true (same pooled object)
System.out.println(a == c); // false (different object)
System.out.println(a.equals(c)); // true (same characters)
System.out.println(a.equalsIgnoreCase("HELLO")); // trueRule of thumb
.equals() (or .equalsIgnoreCase()). Reserve == for primitives like int and boolean.Escape sequences & text blocks
Some characters can't be typed directly inside a string — a newline, a tab, or a quote that would end the string early. For those you use escape sequences, which start with a backslash:
| Escape | Result |
|---|---|
\n | new line |
\t | tab |
\" | a double quote |
\\ | a backslash |
\' | a single quote |
For multi-line text (like JSON, SQL, or HTML), text blocks (Java 15+) are far cleaner — just wrap the content in triple quotes and write it naturally, no escaping required:
String json = """
{
"name": "Sara",
"level": "beginner"
}
""";
System.out.println(json);StringBuilder
Because strings are immutable, joining many pieces with + — especially inside a loop — quietly creates a new object every time, which wastes memory. When you're building a string in many steps, use StringBuilder: a mutable companion you can efficiently append to, insert into, and reverse.
StringBuilder sb = new StringBuilder();
sb.append("Java");
sb.append(" is");
sb.append(" fun");
sb.insert(0, ">> ");
System.out.println(sb); // >> Java is fun
System.out.println(sb.reverse()); // nuf si avaJ >>Note
StringBuffer, which is identical but thread-safe (and slightly slower). Use StringBuilder unless multiple threads share the same builder.Recap & quick check
Key takeaways
- print / println / printf handle output; printf uses %s, %d, %.2f-style placeholders.
- Scanner reads user input — mind the nextInt() then nextLine() buffer trap.
- Strings are immutable: every 'change' returns a brand-new string.
- Compare text with .equals(), never with == (which compares object identity).
- Use text blocks for multi-line text and StringBuilder for efficient step-by-step building.
Quick check
1. How should you check whether two strings contain the same text?
2. What does 'immutable' mean for a String?
3. Which printf specifier prints a decimal rounded to two places?
4. What is the index of the first character in a String?
5. For building a large string across many steps, which is best?
Excellent — your programs can now read, write, and manipulate text like a pro. Next up: Module 4 — Decision Making & Control Flow, where your code starts making choices.