Java.Core.Can different references to the same object (ref0 == ref1) have ref0.equals(ref1) == false?

🚀 Can Different References to the Same Object (ref0 == ref1) Have ref0.equals(ref1) == false?

No, this cannot happen if equals() is correctly implemented.

If two references point to the same object in memory (ref0 == ref1), then equals() must return true, because:

  1. The default equals() method in Object checks for reference equality (==).
  2. A correctly implemented equals() method should always return true for the same object.

However, in a badly implemented equals(), this rule can be

1️⃣ Default equals() Always Returns true for the Same Object

By default, Object.equals() is implemented as:

public boolean equals(Object obj) {
    return (this == obj);
}

📌 If ref0 == ref1, then ref0.equals(ref1) must return true.

Example: Default equals() in Object (Reference Equality)

class Person {
    String name;

    public Person(String name) {
        this.name = name;
    }
}

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person("Alice");
        Person p2 = p1; // Both references point to the same object

        System.out.println(p1 == p2);      // ✅ true (Same object)
        System.out.println(p1.equals(p2)); // ✅ true (Same object, so equals() is true)
    }
}

📌 Since p1 == p2 (same object), equals() must return true.
This works whether equals() is overridden or not.

2️⃣ Can equals() Return false for the Same Object?

🚨 Incorrect Implementation That Breaks equals()

The only way equals() can return false when ref0 == ref1 is if it is incorrectly overridden.

Bad Example: A Broken equals() Method

class Person {
    String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) return false;
        if (obj instanceof Person) {
            Person person = (Person) obj;
            return this.name.equals(person.name) && this != person; // ❌ Incorrect!
        }
        return false;
    }
}

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person("Alice");
        Person p2 = p1; // Same object

        System.out.println(p1 == p2);      // ✅ true
        System.out.println(p1.equals(p2)); // ❌ false (Incorrect behavior)
    }
}

📌 What Went Wrong?

  • The equals() method incorrectly includes this != obj, which forces it to return false for the same object.
  • This violates the reflexivity property of equals().

3️⃣ equals() Must Always Be Reflexive

📜 Java’s equals() Contract

Reflexivity Rule: For any object x, x.equals(x) must return true.

Correct Implementation of equals()

@Override
public boolean equals(Object obj) {
    if (this == obj) return true; // ✅ Reflexivity: Same object should always be equal
    if (obj == null || getClass() != obj.getClass()) return false;
    Person person = (Person) obj;
    return Objects.equals(name, person.name);
}

📌 Why Does This Work?

  • If this == obj, it immediately returns true (reflexivity).
  • If obj is null or a different class, it returns false.
  • Otherwise, it compares content (name).

Now, equals() always returns true for the same object.

📌 Summary: Can ref0 == ref1 and ref0.equals(ref1) == false?

ScenarioExpected equals() ResultWhy?
Default equals() (Object class)trueUses == to check references.
Well-implemented equals()trueEnsures reflexivity (x.equals(x)).
Incorrect equals() ImplementationfalseA bad override can break reflexivity.

✅ Best Practices

Always check if (this == obj) return true; at the start of equals().
Ensure equals() is reflexive (x.equals(x) == true).
Test equals() to avoid breaking hash-based collections like HashSet.

By following these rules, you ensure equals() behaves correctly and efficiently! 🚀

This entry was posted in Без рубрики. Bookmark the permalink.