Course topics

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.

a b c heap string pool "java" "java" new String("java")
Two literals share one pooled object, while new String() creates a separate object with the same characters.

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") are true because both point to the same pooled object.
  • A literal compared to a new String(...) with the same text is false, 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()

Java
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
    }
}
Output
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.

Java · starter code
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
Java · 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.

WebNest Studio

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