String Immutability
Why strings are immutable in Java
Interview Relevant: Critical concept for interviews
6 min read
Understanding String Immutability
In Java, strings are immutable - once a String object is created, its content cannot be changed. Any operation that appears to modify a string actually creates a new String object.
What Does Immutable Mean?
- The internal char array cannot be modified
- Methods like toUpperCase() return NEW strings
- Concatenation creates NEW objects
- The original string remains unchanged
ā Why Immutable?
- Security: Strings used in network, file paths, database queries can't be changed
- Thread Safety: Can be shared between threads without synchronization
- Caching: Enables String Pool for memory optimization
- Hashcode Caching: Hash can be cached since content never changes
ā ļø Performance Impact: String concatenation in loops creates many temporary objects. Use StringBuilder for better performance!
Code Examples
String operations create new objects
java
1// Demonstrating immutability
2String original = "Hello";
3
4// These operations create NEW strings
5String upper = original.toUpperCase();
6String replaced = original.replace('H', 'J');
7String concatenated = original + " World";
8
9// Original is UNCHANGED
10System.out.println(original); // "Hello" (unchanged!)
11System.out.println(upper); // "HELLO" (new object)
12System.out.println(replaced); // "Jello" (new object)
13System.out.println(concatenated); // "Hello World" (new object)
14
15// Visual memory representation:
16// original ā "Hello"
17// upper ā "HELLO"
18// replaced ā "Jello"
19// concatenated ā "Hello World"Security and HashMap benefits
java
1// Why immutability matters for security
2public void connectToDatabase(String connectionString) {
3 // If strings were mutable, this could be changed!
4 // connectionString could be modified after validation
5 validateConnectionString(connectionString);
6
7 // Because strings are immutable, connectionString
8 // cannot be changed between validation and use
9 establishConnection(connectionString);
10}
11
12// Safe to use as HashMap keys
13Map<String, Integer> map = new HashMap<>();
14String key = "myKey";
15map.put(key, 42);
16
17// Even if someone has a reference to 'key',
18// they cannot modify it and break the map
19// key.modify(); // Not possible!
20
21System.out.println(map.get("myKey")); // 42 (always works!)Performance implications and solutions
java
1// Performance problem: String concatenation in loops
2// BAD - Creates many intermediate String objects!
3String result = "";
4for (int i = 0; i < 10000; i++) {
5 result += i; // Creates new String each iteration!
6}
7// This creates ~10000 temporary String objects!
8
9// GOOD - Use StringBuilder
10StringBuilder sb = new StringBuilder();
11for (int i = 0; i < 10000; i++) {
12 sb.append(i); // Modifies same object
13}
14String result2 = sb.toString();
15
16// Performance comparison:
17// Bad approach: O(n²) time, many objects
18// Good approach: O(n) time, one StringBuilder
19
20// Modern approach: String.join or Stream
21String numbers = IntStream.range(0, 10000)
22 .mapToObj(String::valueOf)
23 .collect(Collectors.joining());Hashcode caching and thread safety
java
1// Hash code caching due to immutability
2String str = "Hello";
3
4// First call calculates and caches hash
5int hash1 = str.hashCode();
6
7// Subsequent calls return cached value (faster!)
8int hash2 = str.hashCode(); // No recalculation
9
10System.out.println(hash1 == hash2); // true
11
12// This is why Strings are excellent HashMap keys:
13// 1. Hash never changes
14// 2. Can be cached for performance
15
16// Thread safety from immutability
17String sharedString = "Shared Data";
18
19// Multiple threads can read without synchronization
20Thread t1 = new Thread(() -> System.out.println(sharedString));
21Thread t2 = new Thread(() -> System.out.println(sharedString));
22// No risk of data corruption!
23
24// Contrast with mutable StringBuilder:
25StringBuilder mutable = new StringBuilder("Data");
26// Concurrent access would require synchronizationUse Cases
- Security-sensitive operations (passwords, URLs)
- Multi-threaded applications
- HashMap/HashSet keys
- API design with stable contracts
- Caching and interning
- Configuration values
Common Mistakes to Avoid
- Expecting string methods to modify original
- String concatenation in loops
- Not understanding memory implications
- Assuming reassignment modifies the string
- Not leveraging thread safety benefits
- Using String when StringBuilder is better