2

The expressions used in the following Java code are nuts and pretty much unacceptable though I tested them just for a general purpose and obtained some unexpected result. The simple code snippet goes following.

package wrapper;

final public class Main 
{
    public static void main(String[] args) 
    {
        Integer j1 = 127;
        Integer j2 = 127;
        System.out.println(j1==j2); //returns true!!!

        Integer k1 = 128;
        Integer k2 = 128;
        System.out.println(k1==k2); //returns false!!!

        Integer w1 = -128;
        Integer w2 = -128;
        System.out.println(w1==w2); //returns true!!!

        Integer m1 = -129;
        Integer m2 = -129;
        System.out.println(m1==m2); //returns false!!!
    }
}

Integer j1 = 127;
Integer j2 = 127;
System.out.println(j1==j2);

The above code obviously displays true hence, there is no question about it.


Integer k1 = 128;
Integer k2 = 128;
System.out.println(k1==k2);

The above code is expected to display true on the console but surprisingly, it shows false. Why?


Integer w1 = -128;
Integer w2 = -128;
System.out.println(w1==w2); 

This code displays true and no question about it.


Integer m1 = -129;
Integer m2 = -129;
System.out.println(m1==m2);

The above code again displays false though it is expected to return true. Why?

Lion
  • 18,729
  • 22
  • 80
  • 110
  • FWIW, the same thing happens in Python (the `is` operator is roughly equivalent to Java's `==`): http://stackoverflow.com/questions/306313/python-is-operator-behaves-unexpectedly-with-integers – Greg Hewgill Nov 13 '11 at 18:41
  • Use .equals instead of == for Objects. – Paul Tomblin Nov 13 '11 at 18:41
  • -128 -> 127 are stored at runtime in the JVM to reference instead of creating new objects. The only thing I can think of is it is doing an object comparison rather then calling compareTo. Try replacing Integer with int and you will probably get different results. – Matt Nov 13 '11 at 18:46
  • possible duplicate of [Java wrapper classes object equality - odd behaviour](http://stackoverflow.com/questions/6911419/java-wrapper-classes-object-equality-odd-behaviour) – Dave Newton Nov 13 '11 at 18:47
  • possible duplicate of [Wrapper class and == operator](http://stackoverflow.com/questions/5581913/wrapper-class-and-operator) – Paul Tomblin Nov 13 '11 at 18:57

5 Answers5

9

Integers from the range -128..127 are cached, so j1 and j2 from:

Integer j1 = 127;
Integer j2 = 127;

point to the same object.

Of course, this is a JVM implementation thing, so you should never assume they are cached. For comparing reference types, never use == but use their equals(...) method instead.

Bart Kiers
  • 166,582
  • 36
  • 299
  • 288
4

Note that there's a difference between

int k1 = 128;
int k2 = 128;
System.out.println(k1==k2);

and

Integer k1 = 128;
Integer k2 = 128;
System.out.println(k1==k2);

The first one is creating simple numeric types. The second on is creating Object types which wrap up the numeric types to allow them to be passed to functions which expect Objects.

In the first case, simple numeric types only have a value and this is compared when == is used. However, the Objects which are created don't use == to compare their values. Rather they use == to say if they are the same object and a .equals() method to say if they have the same value. There is no operator overloading in Java, so any time objects are compared with ==, it's always asking the question "is this the same object?" rather than "do these two objects have the same value?"

So, in this case, the code you gave winds up being equivalent to

Integer k1 = new Integer(128);
Integer k2 = new Integer(128);
System.out.println(k1==k2);

This returns false because k1 and k2 are not the same object. If instead you do:

Integer k1 = 128;
Integer k2 = k1;
System.out.println(k1==k2);

You'll get true.

The surprising part is actually that any of the results from your tests above are true. This is caused by the fact that Java keeps a set of Integers for small numbers (-128 to 127, i.e. one byte size) and uses those for assignments when it can.

Keith Irwin
  • 5,628
  • 22
  • 31
3

The == operator checks for reference equality which is not guaranteed to be true in the above code.

To compare if the values are equal use m1.equals(m2).

Paul Tomblin
  • 179,021
  • 58
  • 319
  • 408
dcernahoschi
  • 14,968
  • 5
  • 37
  • 59
1

This happens because of java's integer cache and because you are using the == operator instead of equals().

Using == means comparing references of objects.

Integer A = 135; Integer B = 135;

A==B will evaluate whether their references are the same (whether they are the same object), and not whether they are equal.

Also, if A and B are between (-128, 127), they are cached - meaning if A and B are 35, they will virtually be the same (cached) object, and thats why you get A == B if yhey are in the range above.

Use equals in cases like this.

George
  • 3,727
  • 9
  • 31
  • 47
1

Because it is incorrect to compare objects with == operator, which compares object references for non primitive type. Primitive types can be compared by == operator. Reference types (Integer, Float, Double and other objects) must be compared using equals method.

The reason that sometimes == may work for types like Integer is internal cache. When you declare integer like this:

Integer i = 10;

is equivalent to:

Integer i = Integer.valueOf(10);

For values from -128 to 127 the value is being taken from cache, meaning the same object will be returned by subsequent invocations.

But if you try this:

Integer i1 = new Integer(10);
Integer i2 = new Integer(10);
System.out.println(i1 == i2); // prints false

You will have two different objects and their references are not equal. To get correct result you should compare them as follows:

Integer i1 = new Integer(10);
Integer i2 = new Integer(10);
System.out.println(i1.equals(i2)); // prints true

You should read about equals and hashCode methods and a contract between them

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Igor Nikolaev
  • 4,597
  • 1
  • 19
  • 19