Strings
The string constant pool, string immutability, StringBuilder vs StringBuffer, and immutable classes.
5 questions
MiddleTheoryVery commonWhy is String immutable in Java, and what does that buy you?
Why is String immutable in Java, and what does that buy you?
A String's character contents never change after construction; any method that seems to modify it returns a brand-new String instead. This immutability is what makes pool sharing safe, since no holder can mutate a shared instance. It also lets strings be reliable hash keys, because their hashCode stays stable, and makes them inherently thread-safe to share without synchronization.
Common mistakes
- ✗Thinking methods like
replaceortrimmodify the original string in place - ✗Believing
Stringimmutability requires explicit synchronization to be thread-safe - ✗Forgetting that immutability is the precondition that makes pool sharing safe
Follow-up questions
- →How does immutability allow
Stringto cache itshashCodelazily? - →What security risks would arise if
Stringwere mutable?
MiddleTheoryCommonHow do StringBuilder and StringBuffer differ, and when use each?
How do StringBuilder and StringBuffer differ, and when use each?
Both are mutable string builders that append into a resizable buffer, avoiding the costly reallocation of building a string by repeatedly concatenating immutable String objects. StringBuffer synchronizes every method, so it is thread-safe but slower. StringBuilder is the unsynchronized, faster equivalent. Prefer StringBuilder for single-threaded building and reach for StringBuffer only when one instance is shared across threads.
Common mistakes
- ✗Reaching for
StringBufferby default when no threads are shared, paying for needless locks - ✗Thinking
StringBuilder/StringBufferallocate a newStringon everyappend - ✗Assuming
StringBuilderis thread-safe and sharing one instance across threads
Follow-up questions
- →How does a builder's internal capacity grow as you append past it?
- →Why does the compiler often rewrite
+concatenation intoStringBuildercalls?
JuniorTheoryOccasionalWhat is the string constant pool, and how do literals and new String differ?
What is the string constant pool, and how do literals and new String differ?
The string pool is a JVM-managed cache of interned String objects. Identical string literals share one single pooled object, so a reference check with == on two equal literals is true. Writing new String("x") forces a distinct heap object outside the pool, so == against the literal is false even though equals is true. Calling intern() returns the pooled copy, adding it if absent.
Common mistakes
- ✗Comparing strings with
==and expecting value equality, instead of usingequals - ✗Assuming
new String("x")and the literal"x"are the same object - ✗Believing
intern()is automatic for every string, not just for literals
Follow-up questions
- →Where does the string pool live in memory across modern JVM versions?
- →Why can excessive
intern()use on dynamic strings hurt performance?
SeniorTheoryOccasionalHow do you design your own immutable class in Java correctly?
How do you design your own immutable class in Java correctly?
Mark the class final so it cannot be subclassed and weakened. Make every field private final and set them only in the constructor, exposing no setters or other mutators. For any field of a mutable type, store a defensive copy in the constructor and return a defensive copy from its getter, so callers can never reach the internal state. Then every instance is safely shareable and a reliable hash key, like String.
Common mistakes
- ✗Returning the internal mutable field directly from a getter instead of a defensive copy
- ✗Leaving the class non-
final, letting a subclass add mutable state or override behavior - ✗Storing a passed-in mutable argument by reference without copying it in the constructor
Follow-up questions
- →Why does
recordgive you much of this immutability boilerplate for free? - →How can a final field still be observed in a partially-constructed, unsafe state?
JuniorCodeRarePredict what this concat snippet prints
Predict what this concat snippet prints
It prints qwe. String is immutable, so concat does not modify a in place — it returns a brand-new String "qwerty". That return value is discarded because it is never assigned, leaving a still pointing at the original "qwe". To keep the result you must assign it: a = a.concat("rty");.
Common mistakes
- ✗Believing
concatmutates the receiver string in place - ✗Forgetting that the returned new
Stringis lost when not assigned - ✗Confusing
Stringsemantics with mutableStringBuilder.append
Follow-up questions
- →How would
StringBuilder.appenddiffer in this same snippet? - →What is the smallest change that makes it print
qwerty?