Appearance
Lesson 01 · Text — Strings & Text Blocks
Objectives
After this lesson you will be able to:
- Explain why
Stringis immutable and what the string pool does. - Predict
==vs.equals()results for literals,new String, and concatenations. - Use the high-yield
Stringmethods correctly — especially 0-based indexing and end-exclusivesubstring. - Choose
StringBuilderover repeated concatenation, and avoid itsequalstrap. - Write text blocks and reason about incidental whitespace,
\, and\s.
String is immutable
A String never changes after it's created. Every "modifying" method returns a new String and leaves the original untouched.
java
String s = "java";
s.toUpperCase(); // result thrown away!
System.out.println(s); // java (unchanged)
s = s.toUpperCase(); // reassign to keep the new String
System.out.println(s); // JAVAImmutability is why String is safe to share and cache — which leads directly to the pool.
The string pool & == vs equals
String literals are interned: the JVM keeps one shared copy in the string pool, so equal literals are the same object. new String(...) always creates a distinct object.
java
String a = "hi";
String b = "hi";
String c = new String("hi");
a == b // true — same pooled object
a == c // false — c is a new object
a.equals(c) // true — same characters==compares references (identity)..equals()compares contents — almost always what you want for text.
Exam trap
A compile-time constant concatenation is folded and pooled, but concatenation involving a variable builds a new String at runtime:
java
String x = "hi";
String y = "h" + "i"; // constant → pooled
String p = "h";
String z = p + "i"; // variable → new object at runtime
x == y // true
x == z // false
x == z.intern() // true — intern() returns the pooled copyHigh-yield String methods
Indexing is 0-based, and ranges are end-exclusive (begin inclusive, end exclusive).
java
String s = "hello";
s.length(); // 5 (method, not a field)
s.charAt(0); // 'h'
s.indexOf('l'); // 2 (-1 if not found)
s.substring(1, 3); // "el" (index 1,2 — NOT 3)
s.substring(2); // "llo"
s.replace('l', 'L'); // "heLLo" (all occurrences; original unchanged)
s.contains("ell"); // true
s.toUpperCase(); // "HELLO"
" hi ".strip(); // "hi" (Unicode-aware, Java 11)
"ab".repeat(3); // "ababab" (Java 11)
" ".isBlank(); // true (Java 11)Gotcha
strip() (Java 11+) is Unicode-aware; the older trim() only removes characters <= U+0020. Prefer strip(). Also note replace replaces all occurrences and takes plain text, while replaceAll takes a regex.
What prints? — substring bounds
java
String s = "hello";
System.out.println(s.substring(1, 3));
System.out.println(s.substring(5)); // begin == length is allowed
System.out.println(s.substring(1, 6)); // end > lengthAnswer: el, then an empty line (""), then a StringIndexOutOfBoundsException. substring(5) on a length-5 string is the empty string (valid); end = 6 is out of range and throws.
Concatenation vs StringBuilder
+ on strings is convenient but each operation creates a new String. Building a string in a loop with + is O(n²); use a StringBuilder (mutable, no new object per step).
java
// Avoid: a new String every iteration
String out = "";
for (int i = 0; i < n; i++) out += i;
// Prefer:
var sb = new StringBuilder();
for (int i = 0; i < n; i++) sb.append(i);
String result = sb.toString();StringBuilder methods mutate in place and return this, so calls chain:
java
new StringBuilder("abc").append("d").insert(0, ">").reverse().toString(); // "dcba>"Exam trap
StringBuilder does not override equals — it uses object identity. Two builders with identical contents are not equal:
java
new StringBuilder("a").equals(new StringBuilder("a")); // false
"a".contentEquals(new StringBuilder("a")); // true — compare via StringText blocks (Java 15+)
A text block is a multi-line string literal delimited by """. It removes the noise of \n and escaped quotes — ideal for JSON, SQL, and HTML.
java
String json = """
{
"name": "Ada",
"lang": "Java"
}""";Rules that show up on the exam:
- The opening
"""must be followed by a line terminator —"""hi"""does not compile. - Incidental (leading) whitespace is stripped based on the least-indented line and the position of the closing
""". Move the closing delimiter left to keep more indentation. - A trailing space is normally stripped;
\s(a space escape) preserves it, and a line-ending\is a line continuation (joins with the next line, no newline inserted).
java
String s = """
one \
two"""; // "one two" (\ joins the lines)SDET note
Text blocks make embedded test fixtures (expected JSON/HTML, multi-line CSV) far more readable than escaped one-liners. But remember the value is still a plain String — trailing-newline and indentation rules bite when you compare against an exact expected value. Assert on the exact string and let a failing test show you the real whitespace.
Key Takeaways
Stringis immutable; "modifying" methods return a newString. Reassign to keep the result.- Literals are pooled → equal literals are
==.new Stringis a fresh object. Compare text with.equals(), not==. Constant concatenation is pooled; variable concatenation isn't. - Indexing is 0-based;
substring(begin, end)is end-exclusive;indexOfreturns -1 when absent.strip()beatstrim();replaceis literal,replaceAllis regex. - Use
StringBuilderfor repeated building; its methods chain, but it has no valueequals(usecontentEquals/ compare asString). - Text blocks (
"""): opening delimiter needs a newline; incidental whitespace is stripped relative to the closing""";\continues a line and\skeeps a trailing space.
Lesson Quiz
What does this print?
String s = "java"; s.toUpperCase(); System.out.println(s);
Given String a = "hi"; String c = new String("hi"); which are TRUE? (select all) (select all that apply)
What is "hello".substring(1, 3)?
What happens? System.out.println("hello".substring(1, 6));
Which expression is TRUE?
String x = "hi"; String p = "h"; String z = p + "i";
What does this evaluate to? new StringBuilder("a").equals(new StringBuilder("a"))
Which String methods are Unicode-aware / added in Java 11? (select all) (select all that apply)
Which text block is INVALID (won't compile)?
What is the value of this text block (using \\ line continuation)?
String s = """ one \ two""";Best choice for building a large string inside a loop?
Next: Numeric Values — wrappers, Math & BigDecimal. Run the matching code in labs/src/main/java/com/jse21/m01_values/Text.java.