Fundamentals 5 min read

Why Is Java String Immutable? Understanding Final, Thread Safety, and Performance

This article examines Java's String immutability, detailing how the final character array and private design prevent modification, compares mutable alternatives like StringBuilder and StringBuffer, and discusses their thread safety and performance implications to guide developers in choosing the appropriate class for different scenarios.

Xuanwu Backend Tech Stack
Xuanwu Backend Tech Stack
Xuanwu Backend Tech Stack
Why Is Java String Immutable? Understanding Final, Thread Safety, and Performance

Java's String class is immutable because its internal character array is declared final and private, and the class does not expose methods to modify the stored characters. Each modification creates a new String object.

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];
    // ...
}

When final is applied to a class, it cannot be subclassed; when applied to a method, it cannot be overridden; when applied to a variable, the reference cannot be changed, though the object's internal state may still be mutable.

The character array storing the string is final and private, and String provides no mutating methods.

String is final, preventing subclassing that could break immutability.

StringBuilder and StringBuffer mutability

Both StringBuilder and StringBuffer extend AbstractStringBuilder, which holds a mutable char[] value, allowing in‑place modifications without creating new objects.

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    char[] value;
    // ...
}
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence {
    // ...
}
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence {
    // ...
}

Thread safety

String is thread‑safe due to immutability. StringBuffer is thread‑safe because its methods are synchronized. StringBuilder lacks synchronization and is therefore not thread‑safe.

@Override
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

In multithreaded environments, use StringBuffer for safe modifications; otherwise prefer the faster StringBuilder.

Performance

Immutable String has the lowest performance for concatenation because each change creates a new object. StringBuffer performs better than String due to mutability, but its synchronized methods add overhead. StringBuilder offers the best performance as it is mutable without synchronization, yielding roughly 10‑15% speed improvement over StringBuffer at the cost of thread safety.

Small‑scale data manipulation: use String.

Large‑scale single‑threaded operations: use StringBuilder.

Large‑scale multithreaded operations: use StringBuffer.

Javastringimmutabilitystringbuilderstringbuffer
Xuanwu Backend Tech Stack
Written by

Xuanwu Backend Tech Stack

Primarily covers fundamental Java concepts, mainstream frameworks, deep dives into underlying principles, and JVM internals.

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.