String Intern Method in Java

Naveen AnamaneniUpdated · 4 min read

Literals go into the String pool automatically, but text built while the program runs, from user input, a file, or StringBuilder, does not. The intern() method lets you ask for the pooled version of any string: "if this text is already in the pool, give me that object; if not, add mine and give it back." It's a small method with one clear job, and it explains a lot about how the pool works.

Pooling a Runtime String

intern() returns the pool's copy of the same text
Intern.java▶ Try it
public class Intern {
    public static void main(String[] args) {
        String fromUser = new StringBuilder("Pu").append("ne").toString();
        String literal = "Pune";
        System.out.println(fromUser == literal);
 
        String pooled = fromUser.intern();
        System.out.println(pooled == literal);
        System.out.println(fromUser == pooled);
    }
}
Output
false
true
false

How it works

  1. fromUser is built at runtime by StringBuilder, so it's a separate object, not in the pool. fromUser == literal is false, even though the text is the same.
  2. fromUser.intern() looks up "Pune" in the pool. The literal already put it there, so intern() returns that pooled object: pooled == literal is true.
  3. intern() doesn't change fromUser (strings never change); it returns a different reference.

When Is It Useful?

Imagine reading a million rows from a file where a "city" column has only 50 different values. Without interning, you'd hold a million separate String objects; with city = city.intern();, you'd hold 50, all shared.

Good fitPoor fit
Huge numbers of strings with few distinct valuesStrings that are mostly unique, like names or ids
Long-lived data loaded onceShort-lived values in a request
Memory is tightOrdinary application code

Common Mistakes

Interning everything. It adds a lookup to every string and fills the table with values that are never reused.

Expecting intern() to change the original string. Use its return value.

Comparing with == after interning "most" strings. One un-interned string breaks the comparison silently.

Under the Hood

The pool is a hash table inside the JVM. Since Java 7 it stores ordinary heap objects, so interned strings that nothing refers to any more are garbage collected. The table's size can be tuned with -XX:StringTableSize, and jcmd <pid> VM.stringtable prints statistics about it on a running program. Garbage collectors such as G1 can also remove duplicate string contents automatically with -XX:+UseStringDeduplication, which often saves memory without any intern() calls in your code.

Interview Corner

What does String.intern() do?

It returns a canonical, pooled representation of the string. If the pool already contains a string equal to this one, that pooled object is returned; otherwise this string is added to the pool and returned. Literals are interned automatically, so new String("a").intern() == "a" is true.

Practice

  1. Easy: Build "Java" from "Ja" and "va" with StringBuilder, then show the result of == with the literal "Java" before and after intern().
  2. Harder: Create an array of 100,000 strings by repeating ten city names built with new String(...). Intern each one, and use == on two elements with the same city to show they're now the same object.

Quick check: intern()

4 questions
1What does s.intern() return?
2Are string literals interned?
3Is a string built with StringBuilder in the pool?
4What's the right way to compare text?

Key Takeaways

Was this tutorial helpful?

Lesson 190 of 482