Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird behaviour when using Java ternary operator

When I write my java code like this:

Map<String, Long> map = new HashMap<>()
Long number =null;
if(map == null)
    number = (long) 0;
else
    number = map.get("non-existent key");

the app runs as expected but when I do this:

Map<String, Long> map = new HashMap<>();
Long number= (map == null) ? (long)0 : map.get("non-existent key");

I get a NullPointerException on the second line. The debug pointer jumps from the second line to this method in the java.lang.Thread class:

 /**
     * Dispatch an uncaught exception to the handler. This method is
     * intended to be called only by the JVM.
     */
     private void dispatchUncaughtException(Throwable e) {
         getUncaughtExceptionHandler().uncaughtException(this, e);
     }

What is happening here? Both these code paths are exactly equivalent isn't it?


Edit

I am using Java 1.7 U25

like image 625
radiantRazor Avatar asked Jul 09 '13 13:07

radiantRazor


People also ask

Is it bad to use ternary operator?

Except in very simple cases, you should discourage the use of nested ternary operators. It makes the code harder to read because, indirectly, your eyes scan the code vertically. When you use a nested ternary operator, you have to look more carefully than when you have a conventional operator.

What are the three conditions in a ternary operator?

The conditional (ternary) operator is the only JavaScript operator that takes three operands: a condition followed by a question mark ( ? ), then an expression to execute if the condition is truthy followed by a colon ( : ), and finally the expression to execute if the condition is falsy.

What does the ternary operator do in Java?

Ternary Operator in Java A ternary operator evaluates the test condition and executes a block of code based on the result of the condition. if condition is true , expression1 is executed. And, if condition is false , expression2 is executed.

Which is faster if else or ternary operator in Java?

Moreover, as has been pointed out, at the byte code level there's really no difference between the ternary operator and if-then-else.


1 Answers

They are not equivalent.

The type of this expression

(map == null) ? (long)0 : map.get("non-existent key");

is long because the true result has type long.

The reason this expression is of type long is from section §15.25 of the JLS:

If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.

When you lookup a non-existant key the map returns null. So, Java is attempting to unbox it to a long. But it's null. So it can't and you get a NullPointerException. You can fix this by saying:

Long number = (map == null) ? (Long)0L : map.get("non-existent key");

and then you'll be okay.

However, here,

if(map == null)
    number = (long) 0;
else
    number = map.get("non-existent key");

since number is declared as Long, that unboxing to a long never occurs.

like image 175
jason Avatar answered Sep 25 '22 12:09

jason