Why is the String class immutable?
The String class in Java cannot be changed after creation. Any operation that "modifies" a string actually creates a new string.
Basic Level
The String class in Java cannot be changed after creation. Any operation that “modifies” a string actually creates a new string.
String s = "Hello";
s.concat(" World"); // s is still "Hello", the result must be assigned
s = s.concat(" World"); // now s = "Hello World" (new object)
Why was it designed this way?
- Security — strings are used for file paths, URLs, DB connections
- Thread-safety — strings can be passed between threads without issues
- Memory savings — identical strings are reused (String Pool)
The flip side: storing passwords in String is bad practice (see file 5).
Intermediate Level
String Pool
When creating a string literal, the JVM checks whether such a string already exists in the pool. If it exists — a reference to it is returned, if not — a new one is created:
String a = "Hello";
String b = "Hello";
System.out.println(a == b); // true — the same reference from the pool
Security
Strings are used as parameters when opening files, network connections, and DB connections. If strings were mutable, an attacker could pass a valid path, wait for the check, and then change it in memory.
hashCode stability
String caches its hashCode() on the first computation. This makes strings ideal keys for HashMap:
Map<String, Integer> map = new HashMap<>();
map.put("key", 42); // hashCode computed once
map.get("key"); // the same hashCode is used
How it’s implemented in JDK
- The class is marked
final(prohibits inheritance) - The internal field
byte[] value(Java 9+) orchar[](older versions) —private final - No methods modify this field
Advanced Level
Architectural significance
Immutability of String is not just a convenience — it’s a fundamental architectural decision on which the following are built:
- String Pool (Flyweight pattern) — without immutability, the pool is impossible: changing a string in one place would break all references to it
- Security Manager — file, network, and class access checks are based on the immutability of string parameters
- Class Loading — class names and load paths are immutable, preventing class substitution
- HashMap stability — cached
hashCodeguarantees correct hash table operation
Implementation evolution
- Java 8 and earlier:
private final char[] value— each character is 2 bytes (UTF-16) - Java 9+:
private final byte[] value+coderfield — Compact Strings (Latin-1 = 1 byte, UTF-16 = 2 bytes) // Replacing char[] with byte[] (Java 9+, Compact Strings) saves ~50% memory for strings with Latin characters.
Summary for Advanced
Stringimmutability is the foundation for String Pool, Security, and Thread Safety- Allows the JVM to optimize memory usage and cache hash codes
- Any “modification” of a string spawns a new object on the heap
- Without
Stringimmutability, the entire Java platform would be vulnerable. Example TOCTOU attack: path/safe/pathis checked, but then the string is changed to/etc/passwd.
Interview Cheat Sheet
Must know:
- String — final class, private field
byte[] value, no modification methods - String Pool — identical strings are reused, works ONLY because of immutability
- Security — strings are used for file paths, URLs, DB connections
- hashCode stability — String caches hashCode, ideal as a HashMap key
- Evolution: Java 8
char[](2 bytes/char) → Java 9+byte[]+ coder (Compact Strings, 1 byte for Latin-1) - Without String immutability, the entire Java platform is vulnerable (TOCTOU attacks)
Frequent follow-up questions:
- Why is String final? — So a subclass cannot add mutability or override hashCode/equals
- What are Compact Strings? — Java 9+: Latin characters stored in 1 byte instead of 2
- Why does String cache hashCode? — Computed once, speeds up HashMap operation
- What would happen without String immutability? — String Pool impossible, Security Manager bypassed
Red flags (DO NOT say):
- “String can be changed via concat” — concat creates a NEW string, the original is unchanged
- “String Pool is in PermGen” — since Java 7+ the pool moved to Heap
- “String immutability is just convenience” — it’s a fundamental architectural decision
- “byte[] means String is mutable” — the field is
private final, no external access
Related topics:
- [[5. What are the consequences of String immutability]]
- [[18. How does String pool work and how is it related to immutability]]
- [[19. Can you change a String value via reflection]]
- [[27. Can you use immutable objects as keys in HashMap]]