String Concatenation in Java — Level 2
A developer-focused deep dive into how Java builds strings at runtime. Learn what objects are created when using the + operator, how StringBuilder avoids extra allocations, and when each approach is best.
Categories
A developer-focused deep dive into how Java builds strings at runtime. Learn what objects are created when using the + operator, how StringBuilder avoids extra allocations, and when each approach is best.
Text
Mr. Oz
Date
Read
10 mins
Level 2

Java strings are immutable. Concatenation with +is compiled to use a builder under the hood, but the lifecycle of that builder depends on where the expression sits. In tight loops, using +can create many short‑lived objects; a single StringBuilderreused across iterations avoids those allocations.
For a single expression like "Hello " + name + "!", the compiler emits something like new StringBuilder().append(...).toString(). That means 1 StringBuilder instance and 1 resultingString object at runtime.
// Roughly equivalent desugaring
String result = new StringBuilder()
.append("Hello ")
.append(name)
.append("!")
.toString();Inside a loop, however, s += part; becomesnew StringBuilder(s).append(part).toString() on every iteration: that is 1 new StringBuilder and 1 newString per iteration, plus the previous sbecomes eligible for GC.
String s = "";
for (String part : parts) {
s += part; // each iteration: new StringBuilder + new String
}With an explicit StringBuilder, you typically allocate 1 builder and 1 finalString (from toString()). Intermediate steps are in the same mutable buffer. Capacity growth may copy the internal char array occasionally, but you avoid per‑iteration builder allocation.
StringBuilder sb = new StringBuilder();
for (String part : parts) {
sb.append(part);
}
String s = sb.toString(); // one final String objectConcatenations of literals (and some final constants) are resolved at compile time with zero runtime allocation for the concatenation itself.
String a = "Hello" + ", " + "world"; // constant folded by compilerModern JDKs may use StringConcatFactory via invokedynamicfor +. The optimization strategy can change, but the guidance remains: prefer a single builder in loops or hot paths; + is fine for simple, non‑loop code.
+ for a handful of concatenations outside loops; it is clear and compiled efficiently.StringBuilder (or StringBuffer if thread‑safe).new StringBuilder(estimatedSize).String.join or streams for joining many values with delimiters.s += x inside nested loops; allocations scale with iterations.append(int), append(double), etc. avoid boxing.Want to go deeper?
Continue to Level 3: Bytecode, invokedynamic & StringConcatFactoryLevel 2

A deeper look at how + and StringBuilderallocate objects under the hood, and when to use each.
Text
Mr. Oz
Duration
10 mins