5

I am not able to understand the difference in the way obj and obj2 objects are created in the following code. In particular, I am not sure how a primitive is cast to an object. Looking at some of the other questions here, I thought this was not possible. But the following program compiles and runs fine. In the first case, the output is false and in the second case it is true.

public class Test {

    public static void main(String args[]){

        Integer num = new Integer(3) ;
        Object obj = num;
        Integer[] integerArr = {1, 2, 3, 4};
        Object[] objArr = integerArr;
        boolean contains = false;

        for (int i = 0; i < objArr.length; i++){
            if (objArr[i] == obj){
                contains = true;
                break;
            }
        }

        System.out.println(contains);

        int num2 = 3 ;
        Object obj2 = num2;
        Integer[] integerArr2 = {1, 2, 3, 4};
        Object[] objArr2 = integerArr2;
        boolean contains2 = false;

        for (int i = 0; i < objArr2.length; i++){
            if (objArr2[i] == obj2){
                contains2 = true;
                break;
            }
        }

        System.out.println(contains2);
    }

}
B M
  • 661
  • 2
  • 6
  • 13
  • 4
    You got lucky. `Integer` objects are cached for small values. – Mysticial Mar 06 '13 at 00:31
  • 1
    Duplicate, duplicate, duplicate .. now just finding them. –  Mar 06 '13 at 00:40
  • This is the dupe with the most votes I could find. http://stackoverflow.com/questions/5117132/integer-wrapper-objects-share-the-same-instances-only-within-the-value-127 – user000001 Mar 06 '13 at 00:49

4 Answers4

4

The == operator between objects tests for identity (if two objects are exactly the same), whereas the equals() method tests for equality (whether two objects have the same value).

Most of the time, you'll be interested in equality. By chance, the example you provide in the question actually works, because Integer objects are cached (usually in the range -127 to 127, although this is configurable), but if you tested for identity using a bigger number, it's quite possible that the test will fail.

For example, this will evaluate to true:

Integer a = 127;
Integer b = 127;
a == b // true

Whereas this will evaluate to false!

Integer a = 128;
Integer b = 128;
a == b // false

Bottom line: play it safe and always use equals() for testing equality between objects.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • 1
    Thanks. I know about the equals method and I do use it, but I was just curious as to why == was working in one of the above cases. – B M Mar 06 '13 at 00:35
3

You have to understand this method from java.lang.Integer

public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

In the first case you create a new Integer object while in the second case the the compiler does the conversion for you by using the cache.

/**
 * Cache to support the object identity semantics of autoboxing for values between
 * -128 and 127 (inclusive) as required by JLS.
 *
 * The cache is initialized on first usage.  The size of the cache
 * may be controlled by the -XX:AutoBoxCacheMax=<size> option.
 * During VM initialization, java.lang.Integer.IntegerCache.high property
 * may be set and saved in the private system properties in the
 * sun.misc.VM class.
 */

Here is the relevant bytecode to see how it ends up calling the Integer constructor or Integer.valueOf:

0: new #2; //class java/lang/Integer
3: dup
4: iconst_3
5: invokespecial #3; //Method java/lang/Integer."<init>":(I)V
8: astore_1
9: aload_1
10: astore_2
11: iconst_4
12: anewarray #2; //class java/lang/Integer
15: dup
16: iconst_0
17: iconst_1
18: invokestatic #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
21: aastore
...
90: iconst_3
91: istore 6
93: iload 6
95: invokestatic #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
98: astore 7
100: iconst_4
101: anewarray #2; //class java/lang/Integer
104: dup
105: iconst_0
106: iconst_1
107: invokestatic #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
110: aastore
111: dup
...
jdb
  • 4,419
  • 21
  • 21
1

== If object1 and object2 are reference types, then == checks if object1 and object2 are both references to the same object.

equals If you use object1.equals(object2) then it compares the actual value of the object

Example:

Use the String.equals(String other) function to compare strings, not the == operator.

The function checks the actual contents of the string, the == operator checks whether the references to the objects are equal.

Srujan Kumar Gulla
  • 5,721
  • 9
  • 48
  • 78
0

In the second case, you're comparing a primitive int to the object Integer array. The JVM is "unwrapping" the object Integer and comparing to the primitive.. thus you do get an equality match in that case.

In the first case you're always comparing an object with another object, and in your example these will never be equal.

rtcarlson
  • 424
  • 4
  • 13