Detailed explanation
For objects whose class uses the default equals() implementation from java.lang.Object, == and equals() both test reference identity: whether two references point to the very same object. Neither comparison checks the objects’ fields or decides whether their contents are logically equivalent. Therefore, two separately created objects compare as unequal even if all their field values match. This distinction matters because creating identical data does not automatically give a class value-based equality in Java.
Consider class Point { int x, y; } followed by Point p1 = new Point(); and Point p2 = new Point();. Both objects initially have x and y equal to zero, because Java gives instance int fields a default value of zero. Nevertheless, p1 == p2 and p1.equals(p2) both return false: the two new expressions create distinct objects. If you instead write Point p3 = p1;, then p1 == p3 and p1.equals(p3) both return true. The assignment copies the reference, not the object, so both variables refer to the same instance.
Under the hood, == is a language operator that directly compares object references; it does not call equals(). By contrast, equals() is an instance method resolved through normal method dispatch. Object.equals() effectively returns this == obj, which explains the matching results when that implementation is used. There is an important inheritance qualification: a class that does not declare equals() may still inherit an overridden version from a superclass. In that case, equals() follows the superclass implementation and need not behave like ==.
The expressions also differ when null is involved. Comparing a reference with null using == is safe, but calling equals() on a null reference throws NullPointerException. For a non-null object using Object.equals(), equals(null) returns false. Interviewers usually expect you to distinguish identity from logical equality, explain the separate-object and shared-reference cases, and mention the inheritance caveat. If Point should compare coordinates instead, it needs a suitable equals() override together with a consistent hashCode() override, especially when instances are used in hash-based collections.
Key points to remember
- With Object.equals(), both == and equals() compare reference identity, not field values.
- Distinct objects compare as unequal even when their fields contain identical values.
- Two references to the same object compare as equal with either approach.
- A class can inherit a superclass’s overridden equals() without declaring its own.
- == supports null operands; calling equals() on a null reference throws NullPointerException.
Common mistakes candidates make
- Assuming equals() always compares object contents automatically.
- Saying every class that does not declare equals() necessarily uses Object.equals(), ignoring superclass overrides.
- Treating == and equals() as interchangeable without considering a null receiver.
Likely follow-up questions
How would you make two Point objects with matching coordinates compare as equal?
Override equals() to compare x and y after appropriate identity, null, and type checks. Also override hashCode() so that equal points produce the same hash code.
Does declaring the variables as Object change which equals() method runs?
No: equals() uses runtime method dispatch, so an override on the actual object’s class is still used. The == operator always compares reference identity for object references, regardless of such overrides.
How can you compare two possibly null references safely?
Use java.util.Objects.equals(a, b), which returns true for two null references and false when exactly one is null. For non-null references, it delegates to a.equals(b), preserving the applicable equality behaviour.
Interview tip: State the Object.equals() assumption first, demonstrate distinct objects versus shared references, and then briefly mention null and inherited overrides.
