10

Why does the following line of code produce a NullPointerException?

Long v = 1 == 2 ? Long.MAX_VALUE : (Long) null;

I understand that unboxing is being performed on null, but why?

Note that

Long v = (Long) null;

Does not produce the Exception.

Vivek Kalkur
  • 2,200
  • 2
  • 21
  • 40
jonderry
  • 23,013
  • 32
  • 104
  • 171
  • You do a v=((1==2)?Long.MAX_VALUE : (Long) null); this is always false, so you always try to cast null to Long. This seems not to be allowed and throws your Exception. – evildead Dec 15 '11 at 02:45
  • Why would you have such a line of code? Intellectual curiosity or is it a snippet from actual production code? – Paul Dec 15 '11 at 02:52
  • 1
    @Paul and evildead, looks like example code to demonstrate ordering of unboxing. – Steven Dec 15 '11 at 02:56
  • @Paul, This is from production, but simplified to produce the exception in simple code. – jonderry Dec 15 '11 at 03:02
  • Why don't you break apart the ternary operator into if/then/else? That may help you puzzle this out. – Paul Dec 15 '11 at 03:02
  • It's from production? Once again, readability wins out over cleverness... – Paul Dec 15 '11 at 03:02
  • @Paul If you break it out in to if/then/else theproblem goes away. – Tom Hawtin - tackline Dec 15 '11 at 03:05
  • Breaking it into if then else causes the exception to go away. I'm just wondering why the ternary syntax causes this exception. – jonderry Dec 15 '11 at 03:08
  • 1
    Related: http://stackoverflow.com/questions/3882095/booleans-conditional-operators-and-autoboxing Solution is by the way to move that cast to your `Long.MAX_VALUE` as that returns `long`. – BalusC Dec 15 '11 at 03:08
  • @Tom, then they should remove all such instances from the code, make the guy who wrote them buy donuts for the team, then read up on order of precedence. – Paul Dec 15 '11 at 03:10
  • It has everything to do with http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.25 – Steven Dec 15 '11 at 03:01

2 Answers2

9

So it looks obvious that you only have to box if the condition is true, and there should be no boxing if the condition is false. However the ternary operator expression must have a particular static type. So we have Long and long. The JLS states that the result will be the primitive (just as well - imagine if the operator was, say, + or even ==). So the ternary operator will force the unboxing, and only then does the assignment cause a boxing.

If you were to replace the code with the equivalent if-else, then you'd just have an assignment from long to Long and from Long to Long, which wouldn't have any unboxing and so run fine.

IIRC, this is covered is Bloch & Gafter's Java Puzzlers.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
0

From the JSL

  1. If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression.
  2. If one of the second and third operands is of type boolean and the type of the other is of type Boolean, then the type of the conditional expression is boolean.

In following statement the type of second operand is long and third is Long.

Long v = 1 == 2 ? Long.MAX_VALUE :  (Long) null;

This will work if an expression is true.

Long v= 1 == 1 ?  Long.MAX_VALUE : (Long) null;

Or you may cast it.

Long v= 1 == 2 ?  Long.valueOf(Long.MAX_VALUE) : (Long) null;
KV Prajapati
  • 93,659
  • 19
  • 148
  • 186
  • Yes, I know it's doing unboxing, and that you can't unbox null. I was asking why it is trying to perform unboxing in this case. – jonderry Dec 15 '11 at 02:59
  • That's not entirely correct. He's trying to unbox a null `Long` object; the cast is not the problem. You can cast `null` to any type of object, see the Java Language Spec [section 5.5](http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.5), under "If a cast to a reference type is not a compile-time error, there are several cases:" – Paul Dec 15 '11 at 03:00