PCSalt
YouTube GitHub
Back to Java
Java (Updated: )

== vs equals() in Java — What's the difference?

Understanding the difference between the == operator and equals() method in Java, and why using the wrong one leads to subtle bugs.


Java has two ways to check equality: the == operator and the equals() method. They do different things, and confusing them is one of the most common bugs in Java.

The short version

  • == compares references — are these two variables pointing to the same object in memory?
  • equals() compares values — do these two objects contain the same data?

For primitives (int, boolean, char, etc.), == compares values directly. The distinction only matters for objects.

See it in action

String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");

System.out.println(s1 == s2);       // true
System.out.println(s1 == s3);       // false
System.out.println(s1.equals(s2));  // true
System.out.println(s1.equals(s3));  // true

Why does s1 == s2 return true but s1 == s3 return false? They all contain "hello".

What’s happening in memory

When you write String s1 = "hello", Java checks the String Constant Pool. If "hello" already exists there, it reuses the same reference. So both s1 and s2 point to the exact same object in memory.

s1 ──┐
     ├──▶ "hello" (in String Constant Pool)
s2 ──┘

s3 ──────▶ "hello" (new object on heap)

new String("hello") forces Java to create a new object on the heap, even though an identical string exists in the pool. So s3 holds a different reference.

  • s1 == s2true — same reference (both point to the pooled string)
  • s1 == s3false — different references (pool vs heap)
  • s1.equals(s3)true — same value (both contain “hello”)

How equals() works in String

The String class overrides equals() from Object to compare character-by-character:

  1. If both references are the same (==), return true immediately
  2. Check if the other object is a String
  3. Compare lengths
  4. Compare each character

This is why equals() returns true for s1 and s3 — it doesn’t care where the objects live in memory, only what they contain.

The null trap

String s1 = null;

s1.equals("hello");  // NullPointerException
"hello".equals(s1);  // false — safe

If there’s any chance a variable could be null, either put the known non-null value first, or use Objects.equals():

Objects.equals(s1, s2);  // null-safe, returns false if either is null

Objects.equals() has been available since Java 7. Use it when either side could be null.

Beyond String

Every class can override equals(). The Object class default implementation just uses == (reference comparison). Most standard library classes override it to compare values:

Classequals() compares
StringCharacter sequence
Integer, Long, etc.Numeric value
ListElements in order
SetSame elements
MapSame key-value pairs
Custom classesWhatever you implement

If you write your own class and don’t override equals(), it falls back to ==.

Quick rules

  • Primitives — use == (it’s the only option)
  • Objects — use equals() to compare values
  • Null-safe comparison — use Objects.equals(a, b)
  • Never use == to compare Strings — it works sometimes (pooled literals) and fails other times (new String), which is worse than always failing
// Don't
if (userInput == "admin") { ... }

// Do
if ("admin".equals(userInput)) { ... }

// Or
if (Objects.equals(userInput, "admin")) { ... }

Source Code

View file on GitHub krrishnaaaa/java-demo-code › src/com/example/demo/string/StringDemo.java