What is the difference between String, StringBuilder, and StringBuffer?
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
String | StringBuilder | StringBuffer | |
|---|---|---|---|
| Mutability | immutable | mutable | mutable |
| Thread safety | safe (immutable, inherently) | not synchronized | synchronized (thread-safe) |
| Performance | fine for few/no modifications | fastest for building/modifying | slower than StringBuilder due to lock overhead |
| Introduced | since 1.0 | Java 5 | since 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.