Java 为什么object.equals(新整数(1))等于true?

Java 为什么object.equals(新整数(1))等于true?,java,Java,我正在努力理解这个Koan: @Koan public void equalsMethodCanBeChangedBySubclassesToTestsIfTwoObjectsAreEqual() { Object object = new Integer(1); assertEquals(object.equals(object), true); assertEquals(object.equals(new Integer(1)), __); // Note:

我正在努力理解这个Koan:

@Koan
public void equalsMethodCanBeChangedBySubclassesToTestsIfTwoObjectsAreEqual() {
    Object object = new Integer(1);
    assertEquals(object.equals(object), true);
    assertEquals(object.equals(new Integer(1)), __);
    // Note: This means that for the class 'Object' there is no difference between 'equal' and 'same'
    // but for the class 'Integer' there is difference - see below
}
据我所知,由于
object
object
类的一个实例,
.equals()
方法没有被覆盖,因此检查对象是否相等

如果
newinteger(1)
创建了一个新实例,那么它应该是
object
的一个单独对象。按照我的思路,正确的答案应该是
false
,但只有
true
才能通过。我的逻辑缺陷在哪里


编辑:我知道-128和127之间的整数是缓存的。如果我对
对象
对象的理解是正确的(如上所述),那么这与此无关。

您正在整数对象实例上调用
equals
。它在运行时被分派到Integer类中的实现(该类认为该整数等于具有相同数值的任何其他整数)。编译时类型(所涉及变量的静态类型)并不(直接)重要

如果不是这样的话,这种工作方式会是怎样的(所涉及的接口根本没有实现):

可比a=1;
可串行化b=1;
资产真实(a等于(b));

请注意,静态方法是在编译时“调度”的。这就是为什么应该使用类名而不是对象实例(被忽略,甚至可以为null,编译器会发出警告)调用它们的原因。

整数覆盖
等于
,并检查底层
int
是否等于另一个
整数
实例的
int
,如果是这样,返回
true
。之所以调用Integer的
equals
方法而不是Object中的方法,是因为
Object
的运行时类型是Integer

Integer是一个对象,但由于被重写的
等于
,因此不使用对象标识

以下所有布尔表达式的计算结果均为true:

    print((new Integer(1).equals(1)));
    print((new Integer(1).equals(new Integer(1))));
    print((((Integer) 1).equals(new Integer(1))));
    print(((Integer) 1).equals(1));

现在考虑自动装箱,它在值范围[-1]中重用实例。以下关于对象相等性的语句的计算结果均为

true

    1 == ((Integer) 1)
    ((Integer) (-128)) == ((Integer) (-128)) // in autoboxing range
    ((Integer) (+127)) == ((Integer) (+127)) // same

    ((Integer) (-200)) != ((Integer) (-200)) // not autoboxing
    ((Integer) (+200)) != ((Integer) (+200)) // same

    ((Integer) (-128)) != (new Integer(-128)) // explicit new instance, so no autoboxing
    ((Integer) (+127)) != (new Integer(+127)) // same
如果新整数(1)创建了一个新实例,那么它应该是一个单独的对象对对象


这就是你错的地方。
=
整数(1)
的新实例将是
false
,但
等于
true

听说过
动态方法调度

当您使用超类引用引用子类对象时,如果子类已重写方法,则将调用此重写方法

因此,尽管您使用的是
Object Object=new Integer(1)
,在对象上调用equals将始终调用
Integer.equals()

Integer.equals()
检查整数的相等性,不一定是相同的引用

据我所知,由于
object
object
类的一个实例,
.equals()
方法没有被覆盖,因此检查对象是否相等

你完全搞错了。即使变量
object
的静态类型是
object
,它仍然是
整数的实例。这就是为什么
equals()
被定向到
Integer
的覆盖,从而产生正确的结果


将实例分配给基类型的变量或类实现的接口不会“剥离”对象的子类行为。特别是,
Integer
的实例保留其在
Integer
类中实现的所有行为,即使您已将该实例分配给类型为
Object

的变量@sidgate No的可能重复项,但该实例与“equals vs.=”完全无关不要忘记接受答案@Thilo-Good call-删除了不正确的注释。因此,koan中的注释
//注意:这意味着对于类“Object”,实际上没有在koan中演示“equal”和“same”之间的区别,因为它实际上是被调用的
Integer.equals()
。正确。对象的运行时类型为Integer,因此您调用的不是object.equals,而是Integer.equals。
    1 == ((Integer) 1)
    ((Integer) (-128)) == ((Integer) (-128)) // in autoboxing range
    ((Integer) (+127)) == ((Integer) (+127)) // same

    ((Integer) (-200)) != ((Integer) (-200)) // not autoboxing
    ((Integer) (+200)) != ((Integer) (+200)) // same

    ((Integer) (-128)) != (new Integer(-128)) // explicit new instance, so no autoboxing
    ((Integer) (+127)) != (new Integer(+127)) // same