Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - boxing integer - why it return true if should return false

I'm comparing two pieces of code

Integer x = new Integer(0), y;
y=x;
x+=0;
System.out.println(x==y); // prints false

And

Integer x = 0, y;
y=x;
x+=0;
System.out.println(x==y); // prints true

Shouldn't both return false? It's not primitive variable and somehow in the second code even after adding zero, it prints true. I know about boxing (for Integer from -128 to 127) but then why boxing works in the second piece of code and not on the first one?

like image 718
sycyhy Avatar asked Nov 24 '15 08:11

sycyhy


3 Answers

Shouldn't both return false?

The line

x += 0;

is the same as

x = Integer.valueOf(x.intValue() + 0);

so you see it uses boxing and unboxing to complete the operations.


The second example only uses boxing so it works as expected.

In the first example, you explicitly avoid boxing with

Integer x = new Integer(0);

This forces it to create a new object which is different to the boxed object.

If you do

Integer x = Integer.valueOf(0);

it will behave the same as the second example.

like image 156
Peter Lawrey Avatar answered Nov 15 '22 20:11

Peter Lawrey


no, because the Integer in the range of -128 - 127 are getting cached. In your first example you are explicity creating a new Integer, despite the fact that each Integer in the range of -128 - 127 would refer to the same object.

You can notify this if you add something in your first example. Notify that this will only work in the Integer range of -128 - 127

Integer x = new Integer(0), y;
Integer z = 0; // refers to the cached value.
y=x;
x+=0;
System.out.println(x==z); // This will now print true, since x+=0 will return the cached Integer.

Your second example wont work anymore aswell if you would change the value x to something different, for example 360

like image 45
SomeJavaGuy Avatar answered Nov 15 '22 19:11

SomeJavaGuy


[update] Using new Integer(int) is guaranteed to always result in a new object whereas Integer.valueOf(int) allows caching of values to be done by the compiler, class library, or JVM.

To explain I have written below code and used javap tool, command to generate below code I used javap -c <Classname> which gives you byte code.

    Integer x = new Integer(0), y;
    y=x;
    x+=0;
    System.out.println(x==y); // prints false

enter image description here

If you will see in the above code it creates new object with dynamic memory allocator which is new. Now in second case as below:

    Integer x = 0, y;
    y=x;
    x+=0;
    System.out.println(x==y); // prints true

enter image description here

As said by Peter it uses valueOf method which means it is comparing same object at run time so it will return true with object comparison operator (==). But in first case it was creating new object which is conspicuous in below debugging snapshot:

enter image description here

I hope this helps. :)

By the way Kevin Esche answer also adds to the question. Because it is basically referencing to cached object, try to relate it in case of String. If you are using new String("some_string") it will create new object else if available it will use from string pool. And remember you are using wrapper classes not primitive.

like image 27
Vishrant Avatar answered Nov 15 '22 18:11

Vishrant