I want to compare two Long objects values using if
conditions. When these values are less than 128, the if
condition works properly, but when they are greater than or equal to 128, comparison fails.
Example:
Long num1 = 127;
Long num2 = 127;
if (num1 == num2) {
// Works ok
}
Comparison on the code above works properly, but fails in the code below:
Long num1 = 128;
Long num2 = 128;
if (num1 == num2) {
// Does NOT work
}
Why is there a problem in comparing Long variables with values greater than 127? If the variables data types are changed to long primitives, then the comparisons work for all cases.
TL;DR
Java caches boxed Integer instances from -128
to 127
. Since you are using ==
to compare objects references instead of values, only cached objects will match. Either work with long
unboxed primitive values or use .equals()
to compare your Long
objects.
Long (pun intended) version
Why there is problem in comparing Long variable with value greater than 127? If the data type of above variable is primitive (long) then code work for all values.
Java caches Integer objects instances from the range -128 to 127. That said:
127
(cached), the same object instance will be pointed by all references. (N variables, 1 instance)128
(not cached), you will have an object instance pointed by every reference. (N variables, N instances)That's why this:
Long val1 = 127L;
Long val2 = 127L;
System.out.println(val1 == val2);
Long val3 = 128L;
Long val4 = 128L;
System.out.println(val3 == val4);
Outputs this:
true
false
For the 127L value, since both references (val1 and val2) point to the same object instance in memory (cached), it returns true
.
On the other hand, for the 128 value, since there is no instance for it cached in memory, a new one is created for any new assignments for boxed values, resulting in two different instances (pointed by val3 and val4) and returning false
on the comparison between them.
That happens solely because you are comparing two Long
object references, not long
primitive values, with the ==
operator. If it wasn't for this Cache mechanism, these comparisons would always fail, so the real problem here is comparing boxed values with ==
operator.
Changing these variables to primitive long
types will prevent this from happening, but in case you need to keep your code using Long
objects, you can safely make these comparisons with the following approaches:
System.out.println(val3.equals(val4)); // true
System.out.println(val3.longValue() == val4.longValue()); // true
System.out.println((long)val3 == (long)val4); // true
(Proper null checking is necessary, even for castings)
IMO, it's always a good idea to stick with .equals() methods when dealing with Object comparisons.
Reference links: