提问人:Jared 提问时间:12/5/2021 最后编辑:Zoe is on strikeJared 更新时间:12/5/2021 访问量:195
可变的 Java 对象是否等于自身?[已关闭]
Does a mutable Java object equal itself? [closed]
问:
我在想可变对象,以及它们是如何奇怪的(但非常酷)。
问题:一个可变对象不能等于它自己吗?
这里唯一需要注意的是,显然您必须重写方法,否则默认检查指针相等性,这将(显然)始终得到满足。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;
}
}
答:
4赞
Turing85
12/5/2021
#1
Object::equals
的文档明确指出:
...
该方法在非 null 对象引用上实现等价关系:
equals
- 它是自反的:对于任何非空引用值,应返回 。
x
x.equals(x)
true
...
虽然我们可以以违反此合同的方式实施(正如 khelwood 在此评论中提到的),但它会产生后果。例如,集合 CopyOnWriteArraySet
将无法正常工作:equals(...)
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;
}
}
(这是我在 betaRide 回答这个问题时使用的代码的变体)
当我们删除 in 的(错误的)实现并使用默认的 -implementation from 时,集合将按预期运行:CopyOnWriteArraySet
equals(...)
Foo
equals(...)
Object
class Foo {
}
评论
0赞
Jared
12/5/2021
你错过了我关于幂等操作的观点。
1赞
Turing85
12/5/2021
你的问题是:“一个可变的对象不能等于它自己吗?我回答了这个问题。此外:您的帖子不包含短语“idem”。
0赞
Jared
12/5/2021
“它是自反的:对于任何非空引用值 x,x.equals(x) 应该返回 true”......这在哪里执行?如果这是真的,那么 equals 方法应该内置同步功能。出于显而易见的(性能)原因,我们可能不希望这样做,但如果使用可变对象和相等是必需的,则需要在其他地方处理(即确保以线程安全的方式访问等)。
0赞
Turing85
12/5/2021
它就在那里执行:在方法的合同中,写在文档中。
1赞
Turing85
12/5/2021
再说一遍:有合同。合同不能(轻易)在技术层面上执行,因此合同是有记录的。我的微不足道的实现和你的实现在同一点打破了契约:反身属性。这两种实现都缺少一个共同的保障措施() - 这将破坏问题的重点。每个允许返回的实现都会导致我上面描述的问题。equals(...)
equals(...)
equals(...)
equals(...)
if (this == o) {return true; }
equals(...)
x.equals(x)
false
评论
equals
equals(...)
equals(...)