jazzabeanie jazzabeanie - 7 months ago 15
Java Question

Why does object.equals(new Integer(1)) equate to true?

I am struggling to understand this 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
}


As far as I understand, because
object
is an instance of the
Object
class, the
.equals()
method has not been overwritten, and therefore checks for object equality.

If
new Integer(1)
creates a new instance, then it should be a separate object to
object
. Following my train of thought, the correct answer should be
false
, but only
true
makes this pass. Where is the flaw in my logic?

Edit: I understand that integers between -128 and 127 are cached. If my understanding of the
object
object is correct (as stated above), then this is irrelevant.

Answer

Integer overrides equals and checks if the underlying int is equal to the int of the other Integer instance, and if so, returns true. The reason why Integer's equals method is invoked, and not the one from Object, is that the runtime type of object is Integer.

Integer is an Object, but due to the overridden equals, no object identity is used.

All following boolean expressions evaluate to 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));

Now consider autoboxing, which reuses instances for values in the range [-128,127]. The following statements about object equality are all evaluating to 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