7

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?

Tunaki
  • 132,869
  • 46
  • 340
  • 423
sycyhy
  • 120
  • 1
  • 6
  • 1
    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. – SomeJavaGuy Nov 24 '15 at 08:38
  • Despite what other answers say -128 - 127 is not dogma, it's just a feature of JVM, which can be tweaked on some versions with `-Djava.lang.Integer.IntegerCache.high` property, and default values may dramatically differ from JVM to JVM, **You should never ever rely on this behaviour!** See http://stackoverflow.com/questions/15052216/how-large-is-the-integer-cache – Boris Treukhov Nov 27 '15 at 16:15

4 Answers4

16

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.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Perhaps if the compiler was smart enough, it could have perhaps ignored increment by `0`? – TheLostMind Nov 24 '15 at 08:41
  • @VinodMadyalkar yes, however it has a side effect such as this. Java is very reluctant to break compatibility even if it doesn't much make sense IMHO. note: `x += 0f` does do something for some values perhaps surprisingly. – Peter Lawrey Nov 24 '15 at 08:53
  • I actually thought about that before commenting. But surely the compiler can do things in normal cases (like in the question) :). This will perhaps prevent several bytecode instructions – TheLostMind Nov 24 '15 at 09:00
  • @VinodMadyalkar the `javac` compiler does almost no optimization. It for example drops comments (wow) and does constant expression evaluation but that is about it. BTW some older javascript compilers don't drop comments and they can slow down the code as a result ;) – Peter Lawrey Nov 24 '15 at 09:02
  • 1
    Oh. Poor JIT. It has to do all the hard work :P. Thank You :) – TheLostMind Nov 24 '15 at 10:23
  • 1
    @VinodMadyalkar *every* time you start the JVM :P – Peter Lawrey Nov 24 '15 at 11:11
  • I'm really glad, that compiler does not optimize, because then the code would be hard to understand after decompilation – Michal Krasny Nov 24 '15 at 11:45
  • @Michal similarly, I think the main reason the javac does so little, is that compilation optimisations improve over time so code optimised one way is hard to understand and reoptimise another way. – Peter Lawrey Nov 25 '15 at 06:54
5

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

SomeJavaGuy
  • 7,307
  • 2
  • 21
  • 33
3

[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.

Vishrant
  • 15,456
  • 11
  • 71
  • 120
1

Because,

Integer x is an object. So == , compares reference and not value.

int x is not an object So == , compares value

Your simple code:

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

int x1, y1;
x1 = 5;
y1 = x1;

System.out.println(x1==y1); // prints true
System.out.println(((Integer) x1).equals(y1)); //prints true

And results:

  • false
  • true
  • true
  • true

best regards

OK - I have seen the response with javap (thanks for that answer) and I understand what I miss. However, I find the piece of code that I propose remains interesting.

Gromph
  • 123
  • 12