Wednesday, August 9, 2017

Boxing the Integer

It was late one night, when I was solving a problem in Java. My code suffered from one of those edge-case failures that let one doubt reality, and for a moment I considered that if I hadn't slept off while debugging and if all this was within a dream.

After some println("here") println("here1")... println("here9999"), I finally reached that line.

Basically,
int x = 4444;
List<Integer> list = new ArrayList<Integer>();
list.add(x);
list.add(x);
println(list.get(0) == list.get(1))  // RETURNS FALSE

Yes it does!

So I checked,
Integer x = 4444;
Integer y = 4444;
println(x == y); // again returns false

Okay...
Integer x = 10;
Integer y = 10;
println(x == y); // TRUE

Integer x = 100;
Integer y = 100;
println(x == y); // TRUE

Integer x = 200;
Integer y = 200;
println(x == y); // FALSE (???)

Integer x = 150;
Integer y = 150;
println(x == y); // FALSE(???)


Integer x = 127;
Integer y = 127;
println(x == y); // TRUE


Integer x = 128;
Integer y = 128;
println(x == y); // FALSE (finally, not a dream!)

My first mistake was that I was thinking in decimal. And the second, more importantly, forgetting that Integer is also a class (well not forgetting exactly).

Now I knew what to google and found this:
https://stackoverflow.com/questions/1700081/why-does-128-128-return-false-but-127-127-return-true-when-converting-to-integ
which also quotes this
http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7

Autoboxing is resolved to Integer.valueOf() at compile time, which caches and reuses some ints (-128 to 127 by default) from a pool. Not for performance but conforming to some convention.

Bottom line, use list.get(0).intValue();