Strings and Immutability
7 pages · ~5 min✓ Reviewed
Builds on OOP in Java. Next up: Exceptions.
Immutability and the String Pool: The Mental Model
1. Immutable Strings
- Immutable = state fixed after construction
concat,replace,toUpperCase,trimreturn a NEW String- Original stays untouched:
s.trim();alone is lost finalclass, private value: nobody can subclass or mutate- Gives thread-safe use, cached hash (HashMap key), safe paths
2. The String Pool
- Pool = JVM-wide table of unique literals, on the heap
- Literal reuses the pooled object:
"a" == "a"is true new String("a")= separate heap object, outside the poolintern()returns the pooled instance
String a = "a"; String n = new String("a"); System.out.println(a == n); System.out.println(n.intern() == a);
false true
3. Constants vs Runtime
| Expression | == | Why |
|---|---|---|
"a" + "b" == "ab" | true | folded at compile time, pooled |
x + "b" == "ab" (non-final x) | false | runtime concat, new object |
== compares references, equals() compares content. Always assign the result: s = s.trim().
equals vs == and Comparing Strings
1. == vs equals()
==compares references: same object?equals()compares content- For Strings you almost always want
equals()
String s1 = "hi", s2 = "hi"; String s3 = new String("hi"); System.out.println(s1 == s2); System.out.println(s1 == s3); System.out.println(s1.equals(s3));
literals share one pooled object; new String makes another
true false true
2. Null-safe and ordering
| Call | Gives | Use when |
|---|---|---|
"admin".equals(input) |
StringBuilder and Efficient String Building
1. What StringBuilder Is
- Mutable char sequence with an internal resizable buffer
append,insert,delete,reverse,setCharAtchange it in place- Each returns
this, so calls can be chained
2. Builder vs Concatenation
+=in a loop makes a new String every pass: O(n^2) copying- One builder:
appendin the loop,toString()once at the end
Text Blocks
1. Syntax and Indentation
- Text block = multi-line literal in
"""(Java 15+) - Content starts on the line after the opening
""" - Common leading whitespace is stripped
- Closing
"""position counts; move it left to keep indent
String json = """ {"id": 1} """;
quotes need no escaping: good for JSON, SQL, HTML
2. Newlines and Escapes
| Item | Effect |
|---|---|
| Line break | kept as \n |
\ at line end |
Immutable Classes, Records and Defensive Copies
1. The Immutable Recipe
- Declare the class final
- All fields
private final - Set them only in the constructor
- No setters
- Never return mutable internals
final on a field stops reassignment only. A final List or Date can still be changed through its methods.
2. Defensive Copies
- Copy in:
new ArrayList<>(list),date.clone() - Copy out:
List.copyOf,Collections.unmodifiableList
Strings and Immutability Cheat Sheet
1. Strings and Comparing
Stringis immutable andfinal; literals are pooled- Methods return a new String, so assign:
s = s.trim() intern()returns the pooled copy
| Check | Compares | Null-safe |
|---|---|---|
a.equals(b) | content | no, NPE if a is null |
a == b | reference only | yes |
"lit".equals(x) |
Check yourself
What does this print?
false true hitoUpperCase()returns a new String, and the result was dropped, sosis unchangednew Stringmakes a separate object:==is false,equalsis true
String s = "hi"; s.toUpperCase(); String t = new String("hi"); System.out.println((s == t) + " " + s.equals(t) + " " + s);
What does y == "ab" give here, and why?
false:xis not final, so the concatenation runs at runtime and makes a new object- With
final String x, it would be a compile-time constant:true
String x = "a"; String y = x + "b";