我对这一切仍然很新鲜,但我正在努力获得我的OCAJP认证(Java)。我记得以前读过我在讨论这个问题时可以覆盖.equals方法:
就我而言,现在这些问题一直很恶劣。扭曲你认为你知道的每件小事,迫使你学习所有的细枝末节。现在我已经猜到了E,但我并不认为D是正确的。当然,我的意思是99.9%,但我认为这是一个基于措辞的技巧问题。
这让我思考,这是真的吗?我的意思是,如果我在考试中得到问题,我现在知道如何回答这个问题,但是在压倒一切的疯狂深深的深渊中,是否有可能创造一种a.equals(a)返回false的情况?我觉得这会让亚里士多德生气...
答案 0 :(得分:47)
请注意a
。 b
和c
是原始包装类的实例(例如Integer,Double等)。这些类是最终的,无法扩展,因此您无法覆盖其equals
实现。
因此a.equals(a)
将始终返回true,因为这些类正确实现了equals
。
答案 1 :(得分:21)
由于equals(...)
不是Object
的最终方法,是的,在不同的情况下很可能 。
@Override
public boolean equals(Object obj) {
return false;
}
然而,这个问题具体说明这些是原始包装(例如Integer,Boolean等),因为这些类是最终的,所以你不能扩展它们,因此a.equals(a)
将始终返回true
。
答案 2 :(得分:7)
但你必须非常邪恶并使用反射和多线程:
如果您运行此代码,竞争条件可能会在比较发生时更改myInt
的内部值。如果你想模拟这个条件,只需在Integer.intValue()
内设置一个断点,在debug中运行代码并点击continue。这将产生延迟,人为地创建竞争条件,控制台将返回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 ) );
}
}
答案 3 :(得分:6)
其他答案已经回答了你的问题 - 不,这对于Java的原始包装类是不可能的。
我将尝试解决“问题背后的问题”:这可能与其他类有关吗?
[...]在压倒一切的疯狂深深的深渊中,是否有可能 创建a.equals(a)返回false的情况?我觉得这样 会让亚里士多德生气...
这实际上是一个很好的问题,答案是:是的,有可能创造这种情况,是的,这会让亚里士多德生气。实际上,我不知道是否会让亚里士多德生气,没有认识他,但对于那些必须使用该代码的人来说肯定会引起很多的悲痛。
事情是:与Object.equals()
相关联的合同:
equals方法在非null上实现等价关系 对象引用:
[...]
它是自反的:对于任何非空引用值x,x.equals(x)应该返回true。
是的,在创建自己的课程时,您可以违反此合同。 (遗憾的是)编译器或运行时没有任何东西阻止你。
但是,很多代码都依赖于这个合同,所以如果你违反它,任何使用equals
的代码都可能以神秘的方式失败。
一个例子:Java自己的Collection类(java.util.Collection
和朋友)依赖于equals
。如果将未正确实现equals
的类的实例放入集合中,则会发生奇怪的事情,例如有时包含实例的集合,有时不包含。