Strings are heavily used in Java applications — from identifiers and keys to logs and network data. To optimize memory and performance, Java uses a technique called string interning, managed through the String Pool.
This tutorial demystifies how interning works, why it matters, and how to use it effectively without falling into subtle bugs.
🧠 What is String Interning?
String interning is a method of storing only one copy of each distinct string value. Java maintains a String Pool — a special memory area where string literals are stored and reused.
🔄 How Interning Works
When you create a string using a string literal, Java automatically adds it to the String Pool:
String a = "hello";
String b = "hello";
System.out.println(a == b); // true (same reference from pool)
When you use new String()
, a new object is created in the heap, not in the pool:
String a = "hello";
String b = new String("hello");
System.out.println(a == b); // false (different references)
✋ Manually Interning Strings
You can use intern()
to explicitly place a string into the pool:
String a = new String("hello");
String b = a.intern();
String c = "hello";
System.out.println(b == c); // true
📦 Real-World Use Cases
- Constant string reuse in logging, configs, or databases
- Key comparisons in
HashMap<String, V>
- String-based protocol handlers (e.g., HTTP headers)
💡 Memory and Performance Benefits
- Saves memory when many identical strings are used
- Speeds up comparison using
==
instead of.equals()
(if interned) - Interned strings are immutable and cached
🔎 When Not to Use Interning
- For dynamic or user-generated content (e.g., form inputs)
- When string content is always unique (e.g., UUIDs)
- Excessive interning can increase GC pressure and permanent memory usage
🧪 Code Examples: Equals vs == with Interning
Without Interning
String x = new String("java");
String y = new String("java");
System.out.println(x == y); // false
System.out.println(x.equals(y)); // true
With Interning
String x = new String("java").intern();
String y = "java";
System.out.println(x == y); // true
🛑 Common Pitfalls
- Confusing
==
with.equals()
- Assuming interning happens with all string creation
- Manually interning too many strings (memory bloat)
🔄 Refactoring Example
❌ Naive Code
if (input == "OK") {
// risky
}
✅ Safer and Faster (with intern)
if ("OK".equals(input)) {
// safe
}
Or:
if (input.intern() == "OK") {
// safe if input is expected to match
}
📌 What's New in Java for String Interning?
Java 7+
- String Pool moved from PermGen to Heap (improves GC flexibility)
Java 11+
- Enhanced
String
methods likeisBlank()
,strip()
— no change to interning
Java 21
- String Templates (Preview) — interning not directly affected but introduces new string mechanics
✅ Best Practices
- Use string literals for common constants — they’re auto-interned
- Avoid
new String("...")
unless necessary - Use
intern()
only when you know a string is likely to repeat - Always use
.equals()
for value comparisons unless both strings are interned
🔚 Conclusion and Key Takeaways
- String interning saves memory and improves performance in Java
- Java automatically interns string literals
- Use
intern()
for deduplication in large-scale apps where strings repeat - Prefer
.equals()
over==
unless interning is guaranteed
❓ FAQ
1. What is the Java String Pool?
A memory area where interned strings are stored and reused.
2. Is intern()
expensive?
It can be — avoid interning high-volume, unique strings.
3. Are string literals always interned?
Yes, at compile time.
4. Where is the String Pool located?
Since Java 7, it's stored in the heap, not PermGen.
5. How to compare interned strings efficiently?
Use ==
only if you’re sure both strings are interned.
6. Should I intern user input?
No — it's unpredictable and may bloat memory.
7. Does equals()
work for non-interned strings?
Yes — it compares content, not reference.
8. Is interning reversible?
No. Once interned, the string stays in the pool until garbage collected (heap-based).
9. Can intern()
be used on StringBuilder.toString()
?
Yes, if you want to deduplicate the result.
10. How to ensure a string is from the pool?
Use intern()
explicitly or define it as a literal.