一个可变的 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;
}
}
(这是我在回答 by betaRide 时使用的代码的变体)
当我们删除 Foo
中 equals(...)
的(错误)实现并使用 equals(...)
中的默认 equals(...)
实现时,集合 CopyOnWriteArraySet
将按预期运行23=] 改为:
class Foo {
}
我在考虑可变对象以及它们的怪异之处(但非常酷)。
问题:可变对象可以不等于自身吗?
这里唯一需要注意的是,显然您必须重写 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 returntrue
....
虽然我们可以以违反此合同的方式实施 equals(...)
(如 khelwood in 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;
}
}
(这是我在回答
当我们删除 Foo
中 equals(...)
的(错误)实现并使用 equals(...)
中的默认 equals(...)
实现时,集合 CopyOnWriteArraySet
将按预期运行23=] 改为:
class Foo {
}