是否可以覆盖.equals,以便a.equals(a)返回false?

Ste*_*ker 32 java equals

我对这一切仍然很新鲜,但我正在努力获得我的OCAJP认证(Java).我记得之前读到过.equals方法可以在我提出这个问题时被覆盖:

来自Enthuware准备材料的问题:

就我而言,现在这些问题一直很恶劣.扭曲你认为你知道的每件小事,迫使你学习所有的细枝末节.现在我猜到了E,但我不认为D是正确的.当然,我的意思是99.9%,但我认为这是一个基于措辞的技巧问题.

这让我思考,这是真的吗?我的意思是,如果我在考试中得到问题,我现在知道如何回答这个问题,但是在压倒一切的疯狂深深的深渊中,是否有可能创造一种a.equals(a)返回false的情况?我觉得这会让亚里士多德生气...

Era*_*ran 47

请注意a.b并且c是原始包装类的实例(例如Integer,Double等).这些类是最终的,无法扩展,因此您无法覆盖它们的equals实现.

因此,a.equals(a)将始终返回true,因为这些类equals正确实现.

  • 有一个警告,问题可能针对:对于'double`值,确实可能存在`d!= d` - 即其值为"Double.NaN"的情况.但是,对于`Double d = Double.valueOf(Double.NaN)`,`equals`方法将为`d.equals(d)`返回`true`. (10认同)
  • @StevetheMaker你总是可以扩展一个非final类,并用`public boolean equals(Object other){return false;}`覆盖equals.这没有任何意义,但你可以做到. (9认同)

Ger*_*ssy 21

既然equals(...)不是最终的方法Object,是的,在不同的情况下很可能.

@Override
public boolean equals(Object obj) {
    return false;
}
Run Code Online (Sandbox Code Playgroud)

然而,这个问题具体说明这些是原始包装(例如整数,布尔等),因为这些类是最终的,所以你不能扩展它们,因此a.equals(a)总会返回true.


Fal*_*lco 7

整数a.equals(a)可以返回false

但你必须非常邪恶并使用反射和多线程:

如果运行此代码,竞争条件可能myInt会在比较发生时更改内部值.如果要模拟这种情况,只需Integer.intValue()在调试中运行代码中设置断点并点击继续.这将产生延迟,人为地创建竞争条件,控制台将返回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 ) );
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然聪明和邪恶,但这段代码并没有利用重写方法(原始问题的措辞)或特定于`.equals`的任何机制.编写线程不安全的代码可以触发各种问题,而不仅仅是这样,因为可以在计算机的RAM附近拿着一根铀-235.:) (3认同)

sle*_*ske 6

其他答案已经回答了你的问题 - 不,这是Java的原始包装类所不可能的.

我将尝试解决"问题背后的问题":这可能与其他课程有关吗?

[...]在压倒一切疯狂的深渊深渊中,是否有可能创造出a.equals(a)返回false的情况?我觉得这会让亚里士多德生气...

这实际上是一个很好的问题,答案是:是的,有可能创造这样的情况,是的,这会让亚里士多德生气.实际上,我不知道是否会让亚里士多德生气,没有认识他,但对于那些必须使用代码的人来说肯定会引起很多的悲痛.

问题是:有一个合同与Object.equals():

equals方法在非null对象引用上实现等价关系:

[...]

它是自反的:对于任何非空引用值x,x.equals(x)应该返回true.

Object.equals的Javadocs

是的,在创建自己的课程时,您可以违反此合同.(遗憾的是)编译器或运行时中没有任何内容阻止您.

但是,很多代码都依赖于这个合同,所以如果你违反它,任何使用的代码equals都可能以神秘的方式失败.

一个例子:Java自己的Collection类(java.util.Collection和朋友)依赖equals.如果将未正确实现的类的实例equals放入集合中,则会发生奇怪的事情,例如有时包含实例的集合,有时不包含.