简体   繁体   中英

Comparing Long to simple integer in Java

I was writing a simple condition

List<Long> path = doSomething(); // returns a list of Long and all equal to -1
if (path.get(0)==-1)
    sysout("first condition works"); // never executes
if (path.get(0).equals(-1))
    sysout("sec condition works");  //never executes
if (path.get(0).equals(new Long(-1)))  
    sysout("third condition works");  //works!

Why is that? Please point me to some article in the official doc files to read more!

Integer                       Long
  ^                            ^
  |                            |        auto-boxing/auto-unboxing
  |                            |
  v                            v
 int -----------------------> long

      primitive promotion

This schema shows what implicit conversions Java can do between different things.

In Java, objects and primitives are unfortunately different beasts: Long and long are not the same things. An implicit conversion from long to Long is called auto-boxing . An implicit conversion from Long to long is called auto-unboxing . This kind of conversion is descibed in section 5.1.8 of the Java Language Specification .

Also, like many other languages, Java has implicit conversions between numeric types. An int is implicitly promoted to a long if it is used in an expression that contains other long s. The contexts in which these promotions can occur are described in section 5.6 of the Java Language Specification .

Note that the literal 1 in Java has type int . The litteral 1L has type long .

Long v = ...
if(v == -1) ...

v is a Long and -1 is an int . Java does not know how to compare objects and primitives: it relies on its implicits conversions rules to do so. Here, -1 is converted (auto-boxed) to an Integer . So, we are comparing the reference of two objects that don't even have the same type: the test fails.

Long v = ...
if(v.equals(-1)) ...

This is the same thing as above, except that it's not a comparision that triggers the implicit conversion, but a method call. equals takes an Object as a parameter, so -1 is converted (auto-boxed) to an Integer . Implicit conversions triggered by method calls are described in section 5.3 of the Java Language Specification .

Long v = ...
if(v.equals(new Long(-1))) ...

Here, we call the Long.equal method with a Long as a parameter, so the test succeeds.

What comparision works, then ?

Long v = ...
if(v.equals(-1L)) ...

-1L is a long . It is passed to a method that expects an Object , so it is implicitly converted (auto-boxed) to a Long . The test succeeds.

Long v = ...
if(v.longValue() == -1) ...

v.longValue() is a long , -1 is an int . -1 is promoted to a long because of the == operator. The test succeeds.

if (path.get(0)!=null && path.get(0).longValue()==-1)
    System.out.println("first condition works");

If you compare long primitives you can use method longValue() .
However you should check Long object for null before calling this method.

Your two first cases are comparing a Long to an Integer (due to autoboxing), and they can never be the same object (naturally).

Your final case is the correct one. Use equals() when comparing objects.

EDIT: Or the longValue()/intValue() etc. methods if you want to use the == operator.

Replace if (path.get(0).equals(-1))

with

if (path.get(0).equals(-1L))

By default, number is treated as Integer in java, and thus the comparison fails.

Take a look at auto-boxing in java for better understanding

Because, equals() expects Object . You can't pass premitive value in equals() method. So, equals(-1) is incorrect.

Use

  if (path.get(0).equals(-1)) //long value

Or

if (path.get(0).longValue()==-1)

Or

if (path.get(0)==-1L)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM