I was thinking about mutable objects and how they’re weird (but very cool).
Question: can a mutable object not equal itself?
Only caveat here is that obviously you must override equals
method, otherwise the default checks pointer equality which will (obviously) always be satisfied.
Edit to Question
Alright, I’ve thoroughly confused everyone, take a look at this program:
import java.util.Random; public class EqualsTest { private static final Random RANDOM = new Random(System.currentTimeMillis()); private int value = 0; public static void main(String... args) { System.out.println("Starting program..."); final EqualsTest test = new EqualsTest(); final Thread modify = new Thread(new Runnable() { public void run() { while (true) test.value = RANDOM.nextInt(Integer.MAX_VALUE); } }); final Thread equals = new Thread(new Runnable() { public void run() { while (true) if (!test.equals(test)) { System.out.println("test didn't equal test"); } } }); modify.start(); equals.start(); } @Override public boolean equals(Object e) { if (!(e instanceof EqualsTest)) return false; final EqualsTest obj = (EqualsTest) e; return this.value == obj.value; } }
Advertisement
Answer
The documentation of Object::equals
clearly states that:
…
The
equals
method implements an equivalence relation on non-null object references:
- It is reflexive: for any non-null reference value
x
,x.equals(x)
should returntrue
.…
While we can implement equals(...)
in a way that violates this contract (as was mentioned by khelwood in this comment), it will have consequences. Collection CopyOnWriteArraySet
, for example, will not function properly:
import java.util.concurrent.CopyOnWriteArraySet; class Ideone { public static void main(String[] args) { final CopyOnWriteArraySet<Foo> foos = new CopyOnWriteArraySet<>(); final Foo foo = new Foo(); foos.add(foo); System.out.println(foos.size()); // prints "1" foos.add(foo); System.out.println(foos.size()); // prints "2" } } class Foo { @Override public boolean equals(Object o) { return false; } }
(This is a variant of the code I used in my answer to this question by betaRide)
The collection CopyOnWriteArraySet
will behave as expected when we remove the (faulty) implementation of equals(...)
in Foo
and use the default equals(...)
-implementation from Object
instead:
class Foo { }