Mastering Java Strings: When to Use String, StringBuilder, or StringBuffer

This article explains the immutability of Java's String, compares the mutable StringBuilder and thread‑safe StringBuffer, provides performance benchmarks, and offers practical guidance on selecting the appropriate class for different coding scenarios, especially for interview preparation.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Mastering Java Strings: When to Use String, StringBuilder, or StringBuffer

Key Points: In Java interviews, candidates are expected to explain why String is immutable, its performance trade‑offs, thread‑safety guarantees, and how to choose between String, StringBuilder, and StringBuffer in real scenarios.

Core Principles

1. String – immutable

String stores its characters in a final char[] (Java 9+ uses a byte[] with a charset flag). The array reference is final and the class itself is final, so once created the content cannot change.

String s = "hello";
s = s + " world"; // creates a new String object, original unchanged

Benefits of immutability:

Thread safety : can be shared without synchronization.

String constant pool : identical literals are reused, saving memory.

Suitable as HashMap keys : hashCode can be cached.

Cost: frequent concatenation creates many temporary objects, increasing GC pressure.

2. StringBuilder – mutable, not thread‑safe

StringBuilder maintains a resizable char[]. When appending, characters are written directly; if capacity is insufficient it expands by 2 n + 2 (n = current capacity).

StringBuilder sb = new StringBuilder(16); // preset capacity
sb.append("hello").append(" ").append("world");
String result = sb.toString();

Because it has no synchronization, it is the preferred choice for string concatenation in single‑threaded code and offers excellent performance.

3. StringBuffer – mutable, thread‑safe

StringBuffer has the same API as StringBuilder but its core methods ( append, insert, delete, etc.) are declared synchronized, guaranteeing thread safety at the cost of extra overhead.

// Simplified StringBuffer.append implementation
@Override
public synchronized StringBuffer append(String str) {
    super.append(str);
    return this;
}

The lock makes it slower than StringBuilder; in modern code it is rarely used directly.

4. Performance comparison

// Benchmark: 100 000 concatenations
// String concatenation: ~3000 ms (creates new object each time)
// StringBuilder: ~5 ms
// StringBuffer: ~8 ms (extra lock cost)

The gap widens with more iterations. The compiler can optimise simple + concatenations to a StringBuilder, but inside a loop the optimisation does not apply, so each iteration creates a new StringBuilder.

5. Selection guide

Scenario: string never changes or only a few concatenations → use String.

Scenario: single‑threaded frequent concatenation/modification → use StringBuilder.

Scenario: multi‑threaded shared mutable string → use StringBuffer (though other concurrency solutions are often preferred).

Frequent Questions

Q: How many objects are created by String s = "a" + "b" + "c"?

A: Compile‑time constant folding turns it into the single literal "abc", stored once in the constant pool.

Q: Why did Java 9 replace char[] with byte[]?

A: Most strings contain only Latin‑1 characters, which need only one byte. Compact Strings store them in a byte[], reducing heap usage by about 20%.

Q: What initial capacity should a StringBuilder have?

A: If the final length can be estimated, pass it to the constructor; avoiding repeated expansions saves time.

Interview Answer Template

String is immutable, backed by a final byte[] (Java 9+), making it thread‑safe and ideal for constant strings or very few concatenations. StringBuilder provides a mutable, unsynchronised buffer, offering the best performance for single‑threaded concatenation. StringBuffer adds synchronized to the same API, ensuring thread safety but with a slight performance penalty; it is suitable when multiple threads need to modify the same string, though modern code often prefers other concurrency mechanisms. A common pitfall is using the + operator inside a loop, which forces the compiler to create a new StringBuilder each iteration; move the StringBuilder outside the loop for optimal speed.
stringstringbuilderstringbuffer
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.