Skip to content

22 · 32 · 5 min

The same object, or an equal one

Two questions that look the same and are not: is this the same object, and does this represent the same value.

java
String a = new String("hello");
String b = new String("hello");

a == b        // false: two objects
a.equals(b)   // true: same value

== compares references. equals compares whatever the class decides.

Why this bites beginners

java
Integer x = 127, y = 127;
x == y        // true

Integer p = 128, q = 128;
p == q        // false

Java caches boxed integers from -128 to 127, so small values are the same object and larger ones are not. The lesson is not to memorise the range; it is to never use == on boxed types or strings.

Python has the same trap with is against ==, for the same reason.

The contract

If you override equals, you must override hashCode, and the rule is:

equal objects must have equal hash codes

Breaking it does not throw. It makes the object unfindable in any hashed collection, which is a silent and confusing failure.

java
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Point p)) return false;
    return x == p.x && y == p.y;
}

@Override
public int hashCode() {
    return Objects.hash(x, y);
}

equals must also be reflexive, symmetric, transitive, consistent, and false for null. Symmetry is the one that breaks in practice, usually when a subclass compares against a superclass and the superclass does not agree.

Records and data classes

java
public record Point(int x, int y) { }

equals, hashCode and toString are generated from the fields, and the fields are final. Python's @dataclass, Kotlin's data class and C# records do the same. For a value type this is the right default, and it removes a recurring source of bugs.

Value or identity

The deeper question is which kind of thing you are modelling.

ValueEntity
Equal whenfields matchidentifiers match
Examplemoney, a date, a coordinatea customer, an order
Should be immutableyesusually not

Two customers with the same name are not the same customer. Two Money(100, INR) are interchangeable. Getting this wrong means either duplicate records or two objects the system refuses to treat as equal.