一个可变的 Java 对象是否等于它自己?

Does a mutable Java object equal itself?

我在考虑可变对象以及它们的怪异之处(但非常酷)。

问题:可变对象可以不等于自身吗?

这里唯一需要注意的是,显然您必须重写 equals 方法,否则默认检查指针相等性(显然)将始终得到满足。

编辑问题

好了,已经把大家彻底糊涂了,看看这个程序:

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

The documentation of Object::equals明确指出:

...

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.

...

虽然我们可以以违反此合同的方式实施 equals(...)(如 khelwood in ), it will have consequences. Collection CopyOnWriteArraySet 所述,例如,将无法正常运行:

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

(这是我在回答 by betaRide 时使用的代码的变体)


当我们删除 Fooequals(...) 的(错误)实现并使用 equals(...) 中的默认 equals(...) 实现时,集合 CopyOnWriteArraySet 将按预期运行23=] 改为:

class Foo {
}

Ideone demo