String Pool in Java
The String pool gives equal interned text one shared String reference. Literals use this sharing, and intern() can request it for text created at runtime. Content equality and reference identity remain different questions.
Why Does Java Have a String Pool?
Strings are used very frequently in Java applications.
Consider:
String a = "Java";
String b = "Java";
String c = "Java";If Java created a separate object for every identical literal, it would use unnecessary memory.
Instead, Java can maintain one pooled "Java" instance and allow multiple references to refer to it.
Conceptually:
String Pool
"Java"
/ | \
a b cExample
String a = "Java";
String b = "Java";
System.out.println(a == b);Output
trueWhy? Because both String literals can refer to the same pooled String object.
String Pool and String Immutability
String pooling works especially well because Strings are immutable.
Suppose:
String a = "Java";
String b = "Java";Both references can safely share the same String object.
If Strings were mutable, changing the object through a could unexpectedly change what b sees.
Because Strings cannot be modified, this sharing is safe.
String Literal vs new
Consider:
String a = "Java";
String b = new String("Java");The literal "Java" can refer to the pooled String.
The new String("Java") expression creates a separate String object.
Therefore:
| Expression | Reference behavior |
|---|---|
String a = "Java"; | Refers to the pooled literal |
String b = new String("Java"); | Creates a separate object, so a == b is false |
String c = b.intern(); | Returns the canonical pooled reference, so a == c is true |
Use equals() to compare string contents; use == only when reference identity is intended.
System.out.println(a == b);Output
falseBut:
System.out.println(a.equals(b));Output
trueThe contents are equal, but the references are different.
The intern() Method
The String class provides an intern() method.
It returns the canonical representation of the String from the String pool.
Example
String a = "Java";
String b = new String("Java");
String c = b.intern();
System.out.println(a == c);Output
trueHere, b.intern() returns the pooled "Java" String.
Understanding intern()
Consider:
String a = "Java";
String b = new String("Java");Conceptually:
String Pool Heap
"Java" "Java"
↑ ↑
a bAfter:
String c = b.intern();c refers to the pooled String:
String Pool Heap
"Java" "Java"
↑ ↑ ↑
a c bTherefore, a == c is true.
Compile-Time String Concatenation
Java can combine constant String expressions at compile time.
For example:
String a = "Java";
String b = "Ja" + "va";The expression can be treated as the same pooled literal value.
Therefore:
System.out.println(a == b);prints:
trueRuntime String Concatenation
Now consider:
String first = "Ja";
String second = "va";
String result = first + second;
String literal = "Java";
System.out.println(result == literal);The result of the concatenation is not necessarily the same reference as the pooled literal.
For modern Java, the compiler typically uses StringConcatFactory/invokedynamic for runtime concatenation.
If you want the pooled canonical representation:
String result = (first + second).intern();Then result == literal can be true.
String Pool and new String()
Consider:
String a = "Hello";
String b = new String("Hello");The String literal "Hello" is associated with the pool.
The new expression creates another String object.
Therefore:
System.out.println(a == b);prints:
falseBut:
System.out.println(a.equals(b));prints:
trueWhere is the String Pool Located?
In modern JVM implementations, the String pool is associated with the heap, not the old permanent generation.
Older Java versions had different memory arrangements, but since Java 7, interned Strings are stored on the heap.
Therefore, avoid the outdated explanation:
"String pool is stored in PermGen."For modern Java, that statement is incorrect.
Is Every String Stored in the String Pool?
No.
Consider:
String a = new String("Java");The String created by new is not automatically the pooled instance.
You can explicitly request the canonical pooled representation:
String b = a.intern();Why is the String Pool Useful?
1. Reduces duplicate String objects
Equal literals can share a pooled instance.
2. Can reduce memory usage
Repeated literals do not necessarily require separate pooled objects.
3. Supports efficient sharing
Immutable Strings can safely be shared.
4. Enables canonical representation
intern() can be used when an application specifically needs canonical String instances.
Should We Always Use intern()?
No.
intern() should not be used automatically for every String.
Interning has a purpose, but excessive or unnecessary interning can increase memory usage and add overhead.
Use it when canonical String identity is useful for the application and the trade-offs are understood.
For ordinary String comparison, use:
a.equals(b);rather than relying on:
a == b;String Pool Example
public class HelloWorld {
public static void main(String[] args) {
String a = "Java";
String b = "Java";
String c = new String("Java");
String d = c.intern();
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a == d);
System.out.println(a.equals(c));
}
}Output
true
false
true
trueExplanation:
a == b — Both can refer to the same pooled String.
a == c — c refers to a separate object created using new.
a == d — d refers to the canonical pooled String returned by intern().
a.equals(c) — Both contain the same characters.
String Pool vs Heap
A simplified view is:
JVM Heap
|
-----------------------
| |
String Pool Other Objects
|
"Java"
"Hello"
"World"The String pool is part of heap-managed memory in modern JVMs.
This diagram is simplified; the JVM's actual memory management is more complex.
Key Takeaway
The String Pool is a JVM-managed collection of canonical String instances that allows Java to reuse equal String literals and explicitly interned strings. Because String objects are immutable, sharing them is safe and can reduce unnecessary duplicate objects.
Remember
String literal
↓
String Pool
↓
Can be shared
new String(...)
↓
New String object
intern()↓ Canonical pooled String
And when comparing String contents: a.equals(b);
is normally the correct choice rather than: a == b;
See you in next page....🙂