Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing boxed Long values 127 and 128

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.

like image 778
Viraj Dhamal Avatar asked Dec 12 '13 10:12

Viraj Dhamal


People also ask

Can we use == to compare long in Java?

== compares references, . equals() compares values. These two Longs are objects, therefore object references are compared when using == operator. However, note that in Long id1 = 123L; literal value 123L will be auto-boxed into a Long object using Long.

Can we compare long and long in Java?

The java. lang. Long. compareTo() method compares two Long objects numerically.

How do you compare long wrapper classes in Java?

Long is a wrapper class for the primitive type long. Since they are objects and not primitive values, we need to compare the content of Long instances using . equals() instead of the reference comparison operator (==).


2 Answers

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:

  • If you set to N Long variables the value 127 (cached), the same object instance will be pointed by all references. (N variables, 1 instance)
  • If you set to N Long variables the value 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:

  • https://today.java.net/pub/a/today/2005/03/24/autoboxing.html
  • https://blogs.oracle.com/darcy/entry/boxing_and_caches_integer_valueof
  • http://java.dzone.com/articles/surprising-results-autoboxing
like image 100
everton Avatar answered Oct 06 '22 00:10

everton


num1 and num2 are Long objects. You should be using equals() to compare them. == comparison might work sometimes because of the way JVM boxes primitives, but don't depend on it.

if (num1.equals(num1)) {  //code } 
like image 42
Nishan Avatar answered Oct 06 '22 01:10

Nishan