Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

In Java, == on object references asks whether two references point to the same object. equals() asks whether objects are logically equal—but only if their class defines that meaning. The distinction matters when comparing values, using objects as map keys or set elements, and working with nullable references.

What does == mean for objects?

For object references, == compares identity: it returns true only when both references designate the same object. It does not inspect the objects’ fields. Oracle’s Object API defines the default equals implementation in the same identity-based way.

String first = new String("Java");
String second = new String("Java");

System.out.println(first == second); // false

The two references above point to separate objects, so == is false even though their contents match. Use == when identity itself is what matters—for example, to check whether a reference is null, or whether two references designate the very same object.

What does equals() compare?

equals() can express logical or value equality: whether two objects contain equivalent information. The Object implementation does not provide that behavior automatically; it returns true only for the same object. A class must override equals() to define value-based comparison. Oracle’s Object methods tutorial illustrates this with distinct Book objects compared by ISBN.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
String first = new String("Java");
String second = new String("Java");

System.out.println(first.equals(second)); // true

Here, String defines equality by content, so two different objects can be equal. For a class that does not override equals(), calling it still has the default identity-based meaning.

How to implement equals() correctly

The Java API requires equality implementations to obey a contract. For non-null references x, y, and z:

  • Reflexive: x.equals(x) is true.
  • Symmetric: if x.equals(y) is true, then y.equals(x) is true.
  • Transitive: if x.equals(y) and y.equals(z) are true, then x.equals(z) is true.
  • Consistent: repeated comparisons return the same result while the state used for comparison has not changed.
  • Null-safe by contract: x.equals(null) returns false.

A typical implementation first handles the same-reference and wrong-type cases, then compares the fields that define equality. The exact fields are a design decision: use the state that makes two instances interchangeable for the class’s intended meaning, not every field indiscriminately.

import java.util.Objects;

final class Book {
    private final String isbn;

    Book(String isbn) {
        this.isbn = isbn;
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) return true;
        if (!(other instanceof Book)) return false;
        Book book = (Book) other;
        return Objects.equals(isbn, book.isbn);
    }

    @Override
    public int hashCode() {
        return Objects.hash(isbn);
    }
}

This example treats books with equal ISBN values as equal and handles a possibly-null ISBN. In production, choose equality fields in line with the class’s domain and inheritance design; equality across a class hierarchy can be difficult to keep symmetric.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why equals() and hashCode() belong together

If two objects are equal according to equals(), they must return the same hashCode(). The reverse is not required: unequal objects are allowed to have the same hash code. Collisions are valid, though excessive collisions can reduce hash-table performance. Oracle documents this contract in the Object API.

This rule is essential for hash-based collections such as HashMap and HashSet. They use a hash code to find a candidate location, then equality to distinguish keys or elements. If a class overrides equals() but retains an identity-based hashCode(), logically equal objects may be placed in different locations and collection lookups can fail unexpectedly. Implement both methods using the same equality-defining fields.

Objects.hash(...) can combine multiple values when implementing a hash code. It is a convenience, not a requirement; any implementation is valid if it satisfies the equal-objects/same-hash-code rule.

How to compare nullable references

Calling a.equals(b) throws NullPointerException if a is null. For a comparison where either reference may be null, use Objects.equals(a, b):

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import java.util.Objects;

Objects.equals(a, b)

The result is true when both references are null, false when exactly one is null, and otherwise the result of calling a.equals(b). This behavior is specified by the Objects API. The helper does not change the equality rules of either object’s class.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When identity equality is intentional

Use IdentityHashMap only for identity-based keys

Ordinary maps rely on key equality and hash codes. IdentityHashMap is a specialized exception: its documentation says keys are considered equal exactly when k1 == k2, rather than when k1.equals(k2). It is explicitly not a general-purpose Map. Use it only when the identity of the key object is the intended distinction.

Avoid identity-sensitive operations on value-based classes

Some Java classes are designated value-based: their equality, hash code, and string representation are derived from state, and equal instances are intended to be interchangeable. Oracle’s value-based classes guidance advises against identity-sensitive operations on these objects, including using ==, identity hash codes, or synchronization. Such operations can have unpredictable results for value-based instances; compare them by value instead.

Which comparison should you use?

Situation Use What it means
Check whether a reference is null value == null Tests whether the reference points to no object.
Check whether two references point to the same object a == b Tests object identity.
Compare object values or logical state a.equals(b) Uses the class’s equality definition; the call requires a non-null receiver.
Compare values when either reference may be null Objects.equals(a, b) Handles nulls, then delegates to the non-null first argument’s equals().
Use keys with ordinary hash-based maps or sets Consistent equals() and hashCode() Equal keys or elements must have matching hash codes.
Use object identity as the map-key distinction IdentityHashMap Keys match only when their references are identical.

What mutability changes

Fields used by equals() and hashCode() determine an object’s logical equality and hash location. If those fields change while an object is stored as a key in a HashMap or as an element in a HashSet, later lookups may no longer find it where the collection placed it. Prefer immutable equality-defining state for objects used in hash-based collections, or avoid changing that state while the object is stored there.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.