jazzabeanie jazzabeanie - 1 year ago 57
Java Question

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

I am struggling to understand this 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
is an instance of the
class, the
method has not been overwritten, and therefore checks for object equality.

new Integer(1)
creates a new instance, then it should be a separate object to
. Following my train of thought, the correct answer should be
, but only
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 is correct (as stated above), then this is irrelevant.

Answer Source

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