可以重写 .equals 使得 a.equals(a) returns 为假吗?
Can .equals be overridden such that a.equals(a) returns false?
我对这一切还很陌生,但我正在努力获得我的 OCAJP 认证 (Java)。我记得以前读过当我遇到这个问题时可以覆盖 .equals 方法:
现在,就我而言,这些问题非常邪恶。扭曲你认为你知道的每一件小事,迫使你学习所有的细节。现在我猜到了 E,但我不认为 D 是正确的。当然,我的意思是 99.9% 的时间,但我认为这是一个基于措辞的技巧问题。
这让我开始思考,这是真的吗?我的意思是,如果我在考试中得到问题,我现在知道如何回答它,但是在压倒一切的疯狂的黑暗深渊中,是否有可能创造一种情况 a.equals(a) returns 错误的?我觉得这会让亚里士多德生气...
注意a
。 b
和 c
是原始包装器 类 的实例(例如 Integer、Double 等)。这些 类 是最终的,不能扩展,因此您不能覆盖它们的 equals
实现。
因此 a.equals(a)
将始终 return 正确,因为那些 类 正确实施 equals
。
您可以查看所有原始包装器的实现,即:整数、布尔值、字符等...您会发现实现是正确的。
原因是使用 equals 时,其中一次检查是检查引用是否相等,并且 x.equals(x) 因为对象和参数是同一个对象。
因为equals(...)
不是Object
的最终方法,是的,很可能在不同的情况下。
@Override
public boolean equals(Object obj) {
return false;
}
然而,这个问题特别指出这些是原始包装器(例如 Integer, Boolean 等),并且由于这些 类 是最终的,您不能扩展它们,因此 a.equals(a)
永远 return true
.
其他答案已经回答了您的问题 - 不,Java 的原始包装器 classes.
无法做到这一点
我会尝试解决 "question behind the question":其他 class 是否可行?
[...] in the deep dark abyss of overriding madness, is it possible to
create a situation where a.equals(a) returns false? I feel like this
would make Aristotle angry...
这其实是一个很好的问题,答案是:是的,有可能造成这样的情况,是的,这会让亚里士多德生气。实际上,我不知道这是否会让不认识亚里士多德的人生气,但这肯定会给那些必须使用代码的人带来很多悲伤。
事情是:有一个 contract 与 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.
是的,创建您自己的 class 时,您可以违反此合同。 (不幸的是)编译器或运行时没有任何东西阻止你。
然而,很多代码都依赖于这个契约,所以如果你违反它,任何使用 equals
的代码都可能会以神秘的方式失败。
一个例子:Java自己的Collectionclasses(java.util.Collection
和朋友)依赖equals
。如果将未正确实现 equals
的 class 实例放入 collection 中,就会发生奇怪的事情,例如 collection 有时包含该实例,有时不包含该实例。
整数 a.equals( a ) 可以 return false
但你必须非常邪恶并使用反射和多线程:
如果您 运行 此代码,则在进行比较时,竞争条件有可能会更改 myInt
的内部值。如果你想模拟这种情况,只需在 Integer.intValue()
运行 调试代码中设置一个断点,然后点击继续。这将造成人为造成竞争条件的延迟,并且控制台将 return false。
class IntegerEqualsTest
{
public static void main( final String[] args )
{
final Integer myInt = new Integer( 420 );
new Thread() {
public void run() {
try {
final Field f = Integer.class.getDeclaredField( "value" );
f.setAccessible( true );
f.setInt( myInt, 100 );
} catch( final Exception e ) {}
}; }.start();
System.out.println( myInt.equals( myInt ) );
}
}
我对这一切还很陌生,但我正在努力获得我的 OCAJP 认证 (Java)。我记得以前读过当我遇到这个问题时可以覆盖 .equals 方法:
现在,就我而言,这些问题非常邪恶。扭曲你认为你知道的每一件小事,迫使你学习所有的细节。现在我猜到了 E,但我不认为 D 是正确的。当然,我的意思是 99.9% 的时间,但我认为这是一个基于措辞的技巧问题。
这让我开始思考,这是真的吗?我的意思是,如果我在考试中得到问题,我现在知道如何回答它,但是在压倒一切的疯狂的黑暗深渊中,是否有可能创造一种情况 a.equals(a) returns 错误的?我觉得这会让亚里士多德生气...
注意a
。 b
和 c
是原始包装器 类 的实例(例如 Integer、Double 等)。这些 类 是最终的,不能扩展,因此您不能覆盖它们的 equals
实现。
因此 a.equals(a)
将始终 return 正确,因为那些 类 正确实施 equals
。
您可以查看所有原始包装器的实现,即:整数、布尔值、字符等...您会发现实现是正确的。
原因是使用 equals 时,其中一次检查是检查引用是否相等,并且 x.equals(x) 因为对象和参数是同一个对象。
因为equals(...)
不是Object
的最终方法,是的,很可能在不同的情况下。
@Override
public boolean equals(Object obj) {
return false;
}
然而,这个问题特别指出这些是原始包装器(例如 Integer, Boolean 等),并且由于这些 类 是最终的,您不能扩展它们,因此 a.equals(a)
永远 return true
.
其他答案已经回答了您的问题 - 不,Java 的原始包装器 classes.
无法做到这一点我会尝试解决 "question behind the question":其他 class 是否可行?
[...] in the deep dark abyss of overriding madness, is it possible to create a situation where a.equals(a) returns false? I feel like this would make Aristotle angry...
这其实是一个很好的问题,答案是:是的,有可能造成这样的情况,是的,这会让亚里士多德生气。实际上,我不知道这是否会让不认识亚里士多德的人生气,但这肯定会给那些必须使用代码的人带来很多悲伤。
事情是:有一个 contract 与 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.
是的,创建您自己的 class 时,您可以违反此合同。 (不幸的是)编译器或运行时没有任何东西阻止你。
然而,很多代码都依赖于这个契约,所以如果你违反它,任何使用 equals
的代码都可能会以神秘的方式失败。
一个例子:Java自己的Collectionclasses(java.util.Collection
和朋友)依赖equals
。如果将未正确实现 equals
的 class 实例放入 collection 中,就会发生奇怪的事情,例如 collection 有时包含该实例,有时不包含该实例。
整数 a.equals( a ) 可以 return false
但你必须非常邪恶并使用反射和多线程:
如果您 运行 此代码,则在进行比较时,竞争条件有可能会更改 myInt
的内部值。如果你想模拟这种情况,只需在 Integer.intValue()
运行 调试代码中设置一个断点,然后点击继续。这将造成人为造成竞争条件的延迟,并且控制台将 return false。
class IntegerEqualsTest
{
public static void main( final String[] args )
{
final Integer myInt = new Integer( 420 );
new Thread() {
public void run() {
try {
final Field f = Integer.class.getDeclaredField( "value" );
f.setAccessible( true );
f.setInt( myInt, 100 );
} catch( final Exception e ) {}
}; }.start();
System.out.println( myInt.equals( myInt ) );
}
}