Skip to content
Advertisement

Does a mutable Java object equal itself? [closed]

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 return true.

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;
  }
}

Ideone demo

(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 {
}

Ideone demo

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement