Why Java Strings Are Final and How Interning Affects Memory
This article explains the two ways to create Java strings, demonstrates how string literals are shared in the method area, shows the effect of the intern() method at runtime, and discusses why the String class is final, immutable, and thread‑safe.
In Java there are two ways to create a string: using a literal (e.g., String x = "abc";) or using the constructor (e.g., String y = new String("abc");). The former stores the literal in the method area, while the latter creates a new object on the heap.
Example 1
String a = "abcd";
String b = "abcd";
System.out.println(a == b); // True
System.out.println(a.equals(b)); // TrueThe expression a == b is true because both a and b reference the same string literal in the method area. Java automatically interns compile‑time string literals, keeping only one copy (string pooling).
Example 2
String c = new String("abcd");
String d = new String("abcd");
System.out.println(c == d); // False
System.out.println(c.equals(d)); // TrueHere c == d is false because each new String creates a distinct object on the heap, giving them different memory references.
Runtime String Interning
Strings can also be interned at runtime using the intern() method, which forces the string to be placed in the method‑area pool.
String c = new String("abcd").intern();
String d = new String("abcd").intern();
System.out.println(c == d); // Now true
System.out.println(c.equals(d)); // TrueAfter interning, c == d becomes true because both references point to the same pooled literal.
Why the String Class Is Final
String Pool Requirement
The string intern pool resides in the method area. When a string is created, if an identical value already exists in the pool, the existing reference is returned instead of allocating a new object. This sharing would be unsafe for mutable strings.
Hashcode Caching
String’s hash code is cached (stored in a private int hash field) to avoid recomputation, which is important for collections like HashMap and HashSet. Immutability guarantees the hash code never changes.
Security
Many Java APIs (e.g., network connections, file handling) accept strings as parameters. If strings were mutable, a malicious change could alter a connection target or file path, leading to security vulnerabilities, including reflection attacks.
Thread‑Safety
Immutable objects can be freely shared across threads without synchronization, eliminating the need for explicit locking.
In summary, for efficiency, security, and thread‑safety reasons, String is designed as an immutable, final class.
Additional Notes
Understanding the difference between immutable objects and immutable references is important. For example: final User user = new User(); The user reference cannot be reassigned, but the User object itself may still be mutable.
Soul Questions
Both String and wrapper classes like Integer are final; why are they not recommended as synchronized lock objects?
Do you know what happens during autoboxing of primitive types?
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
