What is the difference between String, StringBuilder, and StringBuffer?

7 minbeginnerstringstringbuilderstringbuffer

Quick Answer

String is immutable — every modification creates a new object, which is wasteful for repeated concatenation. StringBuilder is a mutable, growable character sequence for efficient in-place string building, but is not thread-safe. StringBuffer is functionally identical to StringBuilder but synchronizes every method, making it thread-safe at the cost of extra overhead that's usually unnecessary since a StringBuffer is rarely actually shared across threads mid-construction.

Detailed Answer

StringStringBuilderStringBuffer
Mutabilityimmutablemutablemutable
Thread safetysafe (immutable, inherently)not synchronizedsynchronized (thread-safe)
Performancefine for few/no modificationsfastest for building/modifyingslower than StringBuilder due to lock overhead
Introducedsince 1.0Java 5since 1.0

String's immutability means every +/concat/replace call allocates a new String object — fine for one-off operations, but wasteful in a loop:

String s = "";
for (int i = 0; i < 1000; i++) {
    s += i; // creates ~1000 intermediate String objects — O(n²) overall
}

StringBuilder avoids this by mutating an internal, resizable character array in place:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
    sb.append(i); // mutates in place — no new object per iteration
}
String result = sb.toString();

StringBuffer behaves identically to StringBuilder but synchronizes every method, making it safe to share across threads — though in practice, a StringBuilder/StringBuffer is almost always built up and converted to a final String entirely within one thread/method before being shared, making that synchronization overhead rarely worth paying. StringBuilder is the default recommendation for essentially all new code; StringBuffer mostly persists for legacy code and rare genuinely-shared-mutable-buffer scenarios.

Note: the compiler automatically optimizes simple, single-expression string concatenation ("a" + b + "c") into efficient StringBuilder calls internally — the manual StringBuilder concern is specifically about concatenation spread across a loop or built up incrementally across multiple statements.