String Interning & String Pool

How Java Saves Memory by Reusing String Objects

CPCS203 - Module 2 | Lesson 2

1 Understanding the Word "Intern"

Before we understand "String Interning" in Java, let's first understand the meaning of the word "intern".

Understanding "Intern" for Arabic Speakers

The English word "intern" has several meanings. In the context of programming:

To intern = يَحتَجِز / يَحجِز في مكان مُخصَّص

Think of it like this:

"To intern a person for investigation"

احتجاز شخص للتحقيق

The person is kept in a special, designated place.

Similarly, String Interning means:

حَجز النصوص في مكان مُخصَّص (String Pool) لإعادة استخدامها

Reserving strings in a designated place (String Pool) for reuse

String Interning Definition

String Interning is a method of storing only one copy of each distinct String value in a special memory area called the String Pool.

This helps save memory when the same String value appears multiple times in a program.

2 What is the String Pool?

The String Pool (also called String Constant Pool or String Intern Pool) is a special area in the Heap memory where Java stores String literals.

Memory Structure: String Pool in the Heap
Heap Memory
String Pool

Special area for interned Strings

"Java"
"Hello"
Regular Heap Area

Objects created with 'new'

new String("Java")

Key Points about the String Pool:

  • It is a special partition within the Heap memory
  • It acts as a repository for String literals
  • Each unique String value is stored only once
  • Multiple variables can share the same String object

3 Real-World Example: Saudi Population Database

Let's imagine we're building a database to store names of the Saudi population. Consider this scenario:

Scenario: 30% of Names are "Abdul Mohsin"

Imagine we have 1,000,000 people and 300,000 of them are named "Abdul Mohsin"!

Abdul Mohsin Abdul Mohsin Abdul Mohsin Mohammed Abdul Mohsin Fahad Abdul Mohsin Khalid Abdul Mohsin Ahmed Abdul Mohsin Abdul Mohsin

"Abdul Mohsin" = 12 characters = approximately 24 bytes per String

Without Interning

300,000 separate String objects

1
2
3
...
...
...

Memory Used: ~7.2 MB

300,000 × 24 bytes

With Interning

Only 1 String object shared by all!

1
← All 300,000 share this!

Memory Used: ~24 bytes

Just 1 × 24 bytes

Memory Saved: Over 7 MB!

This is why String interning is so important for large-scale applications!

4 String Literal vs new String()

There are two ways to create a String in Java. The difference is critical for understanding String interning!

String Literal (Interned)
String s1 = "Java"; String s2 = "Java";
  • Automatically stored in String Pool
  • If same value exists, reuses existing object
  • s1 and s2 point to same object
  • Memory efficient
new String() (Not Interned)
String s3 = new String("Java"); String s4 = new String("Java");
  • Always creates new object in Heap
  • Never reuses existing objects
  • s3 and s4 are different objects
  • Wastes memory if same value
Visual Comparison: Literal vs new String()
Stack Memory
s1
0x100
s2
0x100
s3
0x200
s4
0x300
String Pool (in Heap)
0x100
"Java"
s1 and s2 share this!
Regular Heap
0x200
"Java"
s3's object
0x300
"Java"
s4's object
Notice the Difference!
  • s1 and s2 both point to address 0x100 (same object!)
  • s3 points to address 0x200 (new object)
  • s4 points to address 0x300 (another new object)
  • Using new String() creates 2 extra objects with the same content!

5 Proving String Interning with Code

Let's write code to prove that literal Strings share the same object while new String() creates separate objects.

public class StringInterningDemo { public static void main(String[] args) { // Using String literals (interned) String s1 = "Java"; String s2 = "Java"; // Using new String() (NOT interned) String s3 = new String("Java"); // Compare using == (compares addresses/references) System.out.println("s1 == s2: " + (s1 == s2)); // true System.out.println("s1 == s3: " + (s1 == s3)); // false System.out.println("s2 == s3: " + (s2 == s3)); // false // Compare using .equals() (compares content) System.out.println("s1.equals(s3): " + s1.equals(s3)); // true } }

Output:

s1 == s2: true
s1 == s3: false
s2 == s3: false
s1.equals(s3): true
Understanding the Results
Comparison Result Explanation
s1 == s2 true Same address (both from String Pool)
s1 == s3 false Different addresses (s3 is in regular Heap)
s1.equals(s3) true Same content (both contain "Java")
Critical Difference: == vs .equals()
  • == compares addresses (are they the same object?)
  • .equals() compares content (do they have the same characters?)
  • For Strings, always use .equals() to compare content!

6 The intern() Method

You can manually intern a String using the intern() method:

String s1 = "Java"; String s3 = new String("Java"); String s3Interned = s3.intern(); // Get interned version System.out.println(s1 == s3); // false System.out.println(s1 == s3Interned); // true!

What does intern() do?

  1. Checks if an equal String already exists in the String Pool
  2. If yes, returns a reference to the pooled String
  3. If no, adds this String to the pool and returns its reference

7 Summary

Key Takeaways
  1. String Pool is a special memory area in the Heap for storing unique Strings
  2. String literals (e.g., "Java") are automatically interned
  3. new String() always creates a new object in regular Heap
  4. Interning saves memory by reusing String objects
  5. Use == to compare addresses, .equals() to compare content
  6. Use .intern() to manually add a String to the pool

What's Next?

In the next lesson, we'll explore essential String methods for manipulation, comparison, searching, and conversion!