ReviseAlgo Logo

Strings

String Immutability

Deep dive into the architecture and security reasons behind String immutability in Java.

Interview: Focuses on security implications (classloading, database connection urls), thread safety guarantees, and hashcode caching.

Last Updated: June 13, 2026 10 min read

In Java, the String class is immutable, meaning that once a String object is created on the heap, its character sequence cannot be modified. This design decision was made to support core JVM features including security, memory pooling, and performance caching.

Core Idea

String is a final class backed by a final private array. There are no API methods that can modify the array contents.

Why It Matters

Ensures system security (classloading path validation), thread safety without locks, and O(1) hashcode lookups in collections.

Interview Lens

Focuses on the engineering design rationale for immutability, security vectors, and HashMap optimizations.

Engineering Reasons for Immutability

The String class is designed as immutable for four primary reasons:

  1. Security: Strings are used as parameters for critical configurations (e.g., classloading names, file system paths, database connection strings, network ports). If Strings were mutable, a malicious agent could pass a validated path and then modify it on another thread (TOCTOU vulnerability) to access sensitive data.
  2. String Pool Caching: Immutability allows the JVM to share string objects among multiple references in the String Pool safely. If a string were modified through one reference, it would unexpectedly change values for all other references pointing to the same pool entry.
  3. Thread Safety: Immutable objects are inherently thread-safe. They can be shared across multiple threads without synchronization, eliminating thread lock overhead.
  4. HashCode Caching: Since the character content is immutable, the string's hashcode is guaranteed never to change. The JVM computes the hashcode once during initialization and caches it in a private hash field. This enables constant-time key lookups in HashMap and HashSet.

How Immutability is Enforced

The immutability contract is enforced through class design:

  • The class is declared final, preventing subclasses from overriding methods to inject mutable behavior.
  • The backing array (byte[] or char[]) is declared private final.
  • The class does not expose any setter methods, and internal methods use defensive copying when returning arrays.

Common Pitfalls

  • Assuming Mutability: Expecting methods like toUpperCase() to modify the calling string in-place (e.g. writing str.toUpperCase(); without re-assigning the returned string).
  • Attempting Reflection modifications: Accessing private fields to modify backing arrays. This corrupts String Pool entries, causing unpredictable bugs.
  • Memory retention: Storing sensitive data like passwords as Strings, leaving them in memory until garbage collection runs.

Best Practices

  • Always re-assign variables when using string modification methods: str = str.trim();.
  • Use char[] arrays instead of Strings for passwords so they can be zeroed out immediately after use.
  • Leverage final variables when declaring string configurations to protect runtime invariants.

Interview-Relevant Information

Q1: Why is String declared final?
Answer: If the String class were not final, a developer could subclass it, override its methods to add mutable behavior, and pass it to secure APIs that expect immutable strings. This would compromise classloader stability and security check validations.

Q2: How does String optimize HashMap lookups?
Answer: Because Strings are immutable, their hashcode is guaranteed never to change. The JVM computes the hashcode once and caches it in a private hash field. Subsequent HashMap operations reuse this cached value, providing fast key lookups.

Quick Checklist

Can you explain the security rationale behind immutability, describe how class design enforces immutability, analyze hashcode caching benefits, and prevent reflection hacks? If yes, you understand string immutability.

Use Cases

Protecting security configurations (file paths and class names) from concurrent thread modifications.

Optimizing index retrieval times in large key-value HashMap collections.

Common Mistakes

Calling modification methods without re-assigning the output value.

Attempting to modify private byte arrays via reflection, corrupting JVM state.