Java 为什么object.equals(新整数(1))等于true?
我正在努力理解这个Koan: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
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