Shashika
Shashika

Reputation: 1636

Cannot cast int to long in Java 8

I'm upgrading my project to Java 1.7 to 1.8. When I compile my code, it gives a compile error as int cannot cast to long.

Here is the expression which returns a primitive long.

public Long getOrganizationIdByUser(String userId){

        Query query = getSession().getNamedQuery("getOrganizationIdByUser");
        query.setString("id", userId!=null?_userId.toLowerCase():null);

        List<Long> returnList = query.list();
        return returnList!=null&&returnList.size()>0?returnList.get(0):0;

    }

I've confused why 0 cannot cast to long in java 1.8 since this is a basic concept in java and also it works fine in java 1.7.

Error

error: incompatible types: bad type in conditional expression
    [javac]         return returnList!=null&&returnList.size()>0?returnList.get(0):0;
    [javac]                                                                      
    [javac]     int cannot be converted to Long

Upvotes: 3

Views: 2056

Answers (2)

Holger
Holger

Reputation: 298579

Numeric conditional expressions are subject to “Binary Numeric Promotion”, which is the reason why the following code can be compiled:

Long long1   = null;
Integer int1 = null;
Long long2 = true? long1: int1;

Since both alternatives have a numeric type, the numeric promotion applies, which will first unbox the values, then apply the widening conversion to the int operand, so the conditional expression has a result type of long. Only after, the boxing to Long happens.

So the code above has the unintuitive behavior of throwing a NullPointerException instead of directly assigning the object found in long1 to long2, due to the unboxing and boxing steps.


The same applies to the combination of Long and int, also when the result of the one operand is a method invocation, e.g.

static Long test() {
    return Math.random()<0.5? test(): 0;
}

can be compiled without problems. So what’s the difference? In the example

public Long test() {
    List<Long> returnList = new ArrayList<Long>();
    return returnList!=null&&!returnList.isEmpty()? returnList.get(0): 0;
}

the method invocation is made on an instance of a generic class.

The specification says:

  • If both the second and the third operand expressions are numeric expressions, the conditional expression is a numeric conditional expression.
    For the purpose of classifying a conditional, the following expressions are numeric expressions:

    • An expression of a standalone form (§15.2) with a type that is convertible to a numeric type (§4.2, §5.1.8).

    • A parenthesized numeric expression (§15.8.5).

    • A class instance creation expression (§15.9) for a class that is convertible to a numeric type.

    • A method invocation expression (§15.12) for which the chosen most specific method (§15.12.2.5) has a return type that is convertible to a numeric type.

    • A numeric conditional expression

Note that this has been changed compared to Java 7, due to the introduction of the “standalone form” expression, which is the opposite of the “poly expression” which is subject to target typing.

To check whether the method invocation is a stand-alone expression or a poly expression, we have to refer to JLS §15.12:

A method invocation expression is a poly expression if all of the following are true:

  • The invocation appears in an assignment context or an invocation context (§5.2, §5.3).

  • If the invocation is qualified (that is, any form of MethodInvocation except for the first), then the invocation elides TypeArguments to the left of the Identifier.

  • The method to be invoked, as determined by the following subsections, is generic (§8.4.4) and has a return type that mentions at least one of the method's type parameters.

Otherwise, the method invocation expression is a standalone expression.

In our case, the last bullet does not apply. This method is a member of a generic class, but it is itself not generic as it doesn’t declare type parameters, so it’s return type doesn’t refer to a method’s type parameter, as there is none.

In other words, this method invocation is a stand-alone expression, having a numeric return type, so the conditional expression is a numeric conditional expression, and should be subject to Binary Numeric Promotion, just like the other examples.


Note that all recent Java 9 implementation do compile this code, just like the Java 6 and Java 7 implementations do.

Upvotes: 4

Try adding 'L' at the end :

returnList != null && returnList.size()>0 ? returnList.get(0) : 0L;

Or if 'returnList.get(0)' return an int, try:

returnList != null && returnList.size()>0 ? (long)returnList.get(0) : 0L;

Upvotes: 1

Related Questions