Java interview question
Why are Strings immutable in Java, and when should you use StringBuilder?
Short answer
A String's value cannot change after creation; methods like concat or replace return new objects. Immutability enables the string pool, safe sharing across threads, cached hash codes for HashMap keys, and security. Use StringBuilder when building strings in a loop to avoid creating many intermediate objects.
Answer
A String object’s character content cannot change after it is created. Every method that looks like it modifies a string (concat, replace, toUpperCase, +) returns a new String and leaves the original untouched. The Java designers made this choice because it makes strings safe to share, cache and use as keys.
String s = "order";
s.toUpperCase(); // result discarded; s is still "order"
s = s.toUpperCase(); // s now refers to a new object "ORDER"
Why immutability is useful
- String pool: string literals are interned in a pool, so
"admin"written in 50 places refers to one object. Sharing is only safe because nobody can modify it. - Thread safety: immutable objects can be shared between threads with no synchronisation, which matters in parallel test execution.
- Hash code caching:
Stringcaches itshashCode()after the first computation. Because the content never changes, it is a reliableHashMapkey; a mutable key whose hash changed would be “lost” in the map. - Security and correctness: values such as file paths, URLs, class names and connection strings cannot be altered after they have been validated.
The pool and == versus equals
String a = "qa";
String b = "qa";
String c = new String("qa");
a == b; // true: same pooled literal
a == c; // false: new String creates a separate object
a.equals(c); // true: same characters
c.intern() == a; // true
== compares references. Always compare string content with equals (or equalsIgnoreCase, or Objects.equals(x, y) when either may be null). A test that passes with == today may fail when one value comes from a file, an HTTP response or a database.
StringBuilder for repeated concatenation
Each + in a loop creates a new string and copies all previous characters, so building a long string this way is quadratic in the worst case:
// Avoid in loops
String csv = "";
for (String row : rows) {
csv += row + "\n";
}
// Prefer
StringBuilder sb = new StringBuilder();
for (String row : rows) {
sb.append(row).append('\n');
}
String csv2 = sb.toString();
// Or, when joining a collection
String csv3 = String.join("\n", rows);
For a single expression such as "Hello " + name + "!", plain + is fine: the compiler optimises it (since Java 9 via invokedynamic string concatenation), and it is more readable.
StringBuffer is the older, synchronised equivalent. It is rarely needed because a builder is normally confined to one thread.
Related details
- Text blocks (
"""...""", Java 15+) are convenient for JSON payloads in API tests and are still ordinary immutableStrings. - Because strings are immutable, passwords are sometimes kept in
char[]so they can be wiped after use rather than lingering in memory until garbage collection.
What interviewers look for
- A correct definition: operations return new objects.
- At least two reasons (pool, thread safety, hash caching, security).
==versusequalswith the pool example.- When to use
StringBuilder, and that simple+is fine outside loops.
A strong answer covers
- Strings cannot be changed; operations return new String objects
- String pool and literal interning
- Benefits: thread safety, hashCode caching, security
- Use StringBuilder for repeated concatenation in loops
- Compare strings with equals, not ==