maybesomename
maybesomename

Reputation: 172

Why is Java evaluating the wrong side of ternary operation?

I might miss some simple explanation, but the following line throws a NullPointerException:

Long sum = true 
           ? 
           fiscalDocumentUtil.getFullValue(fiscalDocument.getInvoice()) 
           :
           (long) fiscalDocument.getReceipt().getAmount();

While

Long sum = true 
           ? 
           fiscalDocumentUtil.getFullValue(fiscalDocument.getInvoice()) 
           :
           null

does not. I would also like to mention that

fiscalDocumentUtil.getFullValue(fiscalDocument.getInvoice())

does not throw an exception on its own, while

(long) fiscalDocument.getReceipt().getAmount()

does.

Is the second side evaluated? Or am I butchering something?

EDIT

Some additional info, asked in the comments: fiscalDocumentUtil.getFullValue(fiscalDocument.getInvoice()) returns null. The return type of fiscalDocumentUtil.getFullValue(fiscalDocument.getInvoice()) is Long.

The return type of fiscalDocument.getReceipt().getAmount() is Integer.

If I emit the explicit (long) conversion, the behavior is the same.

Edit 2

A minimal reproducible example: Long val =true ? (Long) null: Integer.valueOf(1);. This was partially suggested by the answer of MC Emperor and partially suggested by comments. Of course, this example already somewhat answers the question, since the second expression does not need to throw an exception, as it turns out.

Upvotes: 1

Views: 229

Answers (2)

ruakh
ruakh

Reputation: 183602

If foo has type Long and bar has type long, then true ? foo : bar has type long, and is equivalent to true ? foo.longValue() : bar. As the Java Language Specification puts it:

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.

(In your case, T is long, and "the result of applying boxing conversion (§5.1.7) to T" is Long.)

The fact that you try to put the result in a Long variable doesn't change that fact; it just gives you the equivalent of Long.valueOf(true ? foo.longValue() : bar), with unboxing followed by boxing.

In your case, foo == null, so the unboxing throws a NullPointerException, so the boxing never happens.

Upvotes: 4

MC Emperor
MC Emperor

Reputation: 23057

Well, Java only evaluates the left expression, as the condition is true.

You said that fiscalDocumentUtil.getFullValue(fiscalDocument.getInvoice()) in itself does not throw an NullPointerException.

The only thing I can think of, is that fiscalDocumentUtil.getFullValue(fiscalDocument.getInvoice()) returns null. Reproducible with:

Long sum = true ? null : (long) 23L;

Because one of the operands is a primitive, the other one is subject to boxing conversion, in this case, unboxed to long.

Upvotes: 1

Related Questions