By WebNest Studio Engineering Team
Java - Core Tutorial
String Comparison and the String Pool
Comparing Strings correctly in Java requires understanding two related concepts: the String Constant Pool, a special area of memory where certain String objects are shared and reused, and the difference between comparing references (==) and comparing content (.equals()). Getting this wrong is one of the most common sources of subtle bugs for Java beginners.
Why it matters
Comparing strings with == is the classic Java bug: it appears to work in simple tests, because literals share one pooled object, and then fails with real data read from a file, a form or a database. Understanding the pool explains both why the bug hides and why equals() is always the correct comparison for text.
How the String Pool Works
When the compiler encounters a String literal, it checks the String Constant Pool first. If an identical String already exists there, the new reference simply points to that existing object instead of allocating a new one. If it does not exist yet, the literal is added to the pool. This pooling only happens automatically for literals — Strings created with new String(...) always bypass the pool and get a distinct object on the heap, even if the same text is already pooled.
== vs .equals()
== on Strings (a reference type) compares whether two variables point to the exact same object in memory, not whether their characters match. .equals(), which String overrides from Object, compares the actual character sequence. Because pooled literals with identical content share one object, == can appear to "work" for literals, which misleads many beginners into using it habitually — until a new String(...) or a runtime-built String breaks the assumption.
- Two identical literals (
"cat" == "cat") aretruebecause both point to the same pooled object. - A literal compared to a
new String(...)with the same text isfalse, because "new" forces a separate heap object. - Content should always be compared with
.equals()(or.equalsIgnoreCase()for case-insensitive checks), never==.
Interning Strings Explicitly
The intern() method lets you manually add a heap-allocated String's content to the pool (or retrieve the existing pooled reference if that content is already there). Calling new String("cat").intern() returns the same reference as the literal "cat", so comparing them with == afterward would be true. Interning is occasionally useful for memory optimization when an application handles huge numbers of duplicate runtime Strings, but it should not be treated as a substitute for using .equals() in ordinary comparisons.
Example
Literals, new String(), and intern() compared with == and .equals()
public class StringPoolDemo {
public static void main(String[] args) {
String a = "cat";
String b = "cat";
String c = new String("cat");
String d = c.intern();
System.out.println("a == b: " + (a == b)); // same pooled object
System.out.println("a == c: " + (a == c)); // c is a separate heap object
System.out.println("a.equals(c): " + a.equals(c)); // same content
System.out.println("a == d: " + (a == d)); // d is interned, points to pool
}
}
a == b: true
a == c: false
a.equals(c): true
a == d: true
Common Mistakes
- Using == to compare String content, which works by accident for pooled literals but breaks silently for Strings built with new or produced at runtime (e.g. via concatenation of variables).
- Assuming every String literal comparison with == is guaranteed true in all cases without understanding it depends on pooling behavior, not the language spec treating "==" as content comparison.
- Thinking intern() changes a String's content — it only affects which pooled reference is returned, never the characters themselves.
- Forgetting that Strings built at runtime through concatenation of non-constant variables are generally not automatically pooled, unlike compile-time constant literals.
Exercise
The method below compares two strings with ==, so the program prints false even though both hold the text "java". Fix the comparison so it prints true, and make it safe when either argument is null.
public class SameText {
static boolean sameText(String x, String y) {
return x == y;
}
public static void main(String[] args) {
String a = "java";
String c = new String("java");
System.out.println(sameText(a, c));
}
}
Show hints
==asks whether both variables refer to the same object.equals()compares the characters.java.util.Objects.equals(x, y)compares content and handles null on either side.
Show solution
import java.util.Objects;
public class SameText {
static boolean sameText(String x, String y) {
return Objects.equals(x, y);
}
public static void main(String[] args) {
String a = "java";
String c = new String("java");
System.out.println(sameText(a, c)); // true
}
}
Quick quiz
1. Given String a = "java"; String b = "java";, what is a == b?
- A. true
- B. false
- C. It depends on the JVM
- D. It does not compile
Show answer
A. Both literals refer to the same object in the string pool, so the references are equal.
2. What is new String("x") == new String("x")?
- A. true
- B. It throws an exception
- C. null
- D. false
Show answer
D. Each new String() creates a separate object, so the two references are different even though the content matches.
3. What is ("hel" + "lo") == "hello"?
- A. It does not compile
- B. false
- C. It depends on the JVM
- D. true
Show answer
D. Concatenating two literals is a compile-time constant. The compiler produces the single literal "hello", which comes from the pool.
Interview questions
What is the string pool and where is it stored?
Show answer
The string pool is a table of unique String objects that the JVM maintains so that identical literals share one object instead of each creating its own. Since Java 7 it is stored in the main heap, which means unused pooled strings can be garbage collected like other objects.
What does intern() do?
Show answer
intern() returns the pooled copy of a String. If an equal string is already in the pool, that one is returned; otherwise this string is added to the pool and returned. After c = c.intern(), a String created with new compares equal with == to the matching literal. In application code you should still compare with equals().
Key Points to Remember
- The String pool stores and reuses literal Strings with identical content to save memory.
- == compares object references; .equals() compares actual character content — always use .equals() for content checks.
- new String(...) always creates a separate object outside the pool, even for text that already exists there.
- intern() manually places a String's content into the pool and returns the shared pooled reference.
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering