Returning Null as an Int Permitted with Ternary Operator But Not If Statement

Returning null as an int permitted with ternary operator but not if statement

The compiler interprets null as a null reference to an Integer, applies the autoboxing/unboxing rules for the conditional operator (as described in the Java Language Specification, 15.25), and moves happily on. This will generate a NullPointerException at run time, which you can confirm by trying it.

Java return null for primitive in ternary

The type of the ternary conditional operator is determined by the types of its 2nd and 3rd operands.

In the case of

input == null ? null : 1

the type is Integer, which can be assigned both null and 1.

The compiler allows your method to return an Integer since it can be auto-unboxed into an int, so it fit the int return type of myMethod.

The fact that your specific code may throw a NullPointerException is not something the compiler can detect.

Unwanted NullPointerException in ternary operator - Why?

When you write

value = condition ? null : 1.0;

the type of condition ? null : 1.0 must be a reference type, so the type is Double, which can hold the value null.

When you write

value = condition ? getDouble() : 1.0;

and getDouble() returns null, it's equivalent to writing:

value = condition ? ((Double) null) : 1.0;

In this case the compiler sees a Double and a double as the 2nd and 3rd arguments of the ternary conditional operator, and decides that type of the expression should be double. Therefore it unboxes the null to double, getting NullPointerException.

The type of the conditional ternary operator is determined by some tables in JLS 15.25.

If the 2nd and 3rd operands are null and double, the conditional expression type is the least upper bound of Double and null, which is Double.

If the 2nd and 3rd operands are Double and double, the conditional expression type is double.

Is there a way to throw an exception in a return statement that uses the ternary operator?

You can use Optional for this

return Optional.ofNullable(bar(a, b))
.orElseThrow(() -> new IllegalArgumentException());

UnexpectedToken error when I try to use return with ternary operator but not with if statement?

Why does this happen?

Because return is a statement, and you can't put statements where only expressions are allowed.¹ The conditional operator's operands must be expressions, not statements. (You'd have the same problem with throw, just FWIW, though there's talk of adding a throw operator... Or with while or for or any other statement.)

The if is probably your best bet.

If you were really, really intent on just using a single expression, you could put the return at the start so the single expression is what follows it:

function monthName(nr) {
return 0 < nr < 13 ? alert("Month: " + months[nr]) : false;
}

Note that that relies on the fact that alert returns undefined in order to maintain the two return values you were providing in your if example (undefined if the alert was shown, false if not). Interestingly, the spec doesn't explicitly say that alert returns undefined but I think we can safely accept that it's implicitly specified (not least because the implicit return of any non-arrow JavaScript function is undefined unless return <value> is used).


¹ (You can do the opposite; JavaScript has the concept of the "expression statement" which means any expression is also a valid statement.)

Java null to int Conditional Operator issue

I did a little debugging and found out that when evaluating

(childCount == 0) ? 100 : null;

the program calls the method valueOf of Integer to evaluate the null. It returns an Integer and as an Integer can be null (and not an int), it compiles. As if you were doing something like:

int roomCode = new Integer(null);

So it is related to autoboxing.

Java: how to avoid NPE in ternary operator, in general how to perform null-checks elegantly?

The problem is that in the ternary expression A ? B : C, if B and C are both compatible numeric types, but one is the boxed object and the other is a primitive, most people would think the result is boxed, by auto-boxing the primitive.

That is not the case. The ternary operator instead unboxes the object, so they are both primitives, and the result is then a primitive.

Which means that the following are the same:

long B = ...;
Long C = ...;

Long R = ... ? B : C;

Long R = (Long) (... ? B : (long) C);

The result is that if C is null, you get NPE.

One way to fix it is to force auto-boxing of B:

Long R = ... ? (Long) B : C;

With that change, a null C value will simply set R = null.

In the case in the question, B is Long.parseLong(rt.getCpu()), so instead of adding a cast to force auto-boxing, use long.valueOf(String s) instead.

Also, unrelated, use isEmpty() instead of equals(""), and there's no need for parentheses around A.

Change the code to:

return new Thresholds(!rt.getCpu().isEmpty() ? Long.valueOf(rt.getCpu()) : defaultPerContainer.getCpu(),
!rt.getMemory().isEmpty() ? Long.valueOf(rt.getMemory()) : defaultPerContainer.getMemory(),
/*omitted for brevity*/);


Related Topics



Leave a reply



Submit