Why are Strings immutable in Java, and what practical benefits does that give you?
Immutability means a String object can never change after it is created. Every operation that looks like a modification — concat, replace, substring, toUpperCase — actually returns a brand-new String and leaves the original untouched. The class is also declared final, so nobody can subclass it to break the guarantee.
The design pays off in four places. Safe sharing. Because a String cannot change, one instance can be passed between threads without any synchronisation. Safe map keys. A HashMap relies on a key's hash code staying the same for the lifetime of the entry; an immutable String can be a key without copying it defensively. Constant hashing. The hash code of a String is computed once and cached, so repeated lookups in a hash-based collection are cheap. String interning. Because equal Strings are interchangeable, the runtime can keep one shared instance per distinct value in the constant pool and hand out references to it.
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
String a = "immutable";
String b = "immutable";
System.out.println("a == b : " + (a == b));
System.out.println("a.equals(b) : " + a.equals(b));
// A String is a safe HashMap key: the hash cannot change under it.
Map<String, Integer> counts = new HashMap<>();
counts.put(a, 1);
counts.put(b, 2);
System.out.println("map size : " + counts.size());
System.out.println("map value : " + counts.get("immutable"));
// The same value can be shared freely between threads.
final String shared = "shared safely";
Thread worker = new Thread(() -> System.out.println("thread sees : " + shared));
worker.start();
try {
worker.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}The counter-intuitive part is that immutability is usually described as a restriction, when in fact it is what makes Strings cheap to work with. You can pass a String to a method that stores it, hand it to a collection, return it from a method, and never worry that somebody else will change it out from under you.