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
How to Get the Current Time in Yyyy-Mm-Dd Hh:Mi:Sec.Millisecond Format in Java
Call an Executable and Pass Parameters
Concurrentmodificationexception Despite Using Synchronized
Returning Null as an Int Permitted with Ternary Operator But Not If Statement
In Java, How to Write a String Literal Without Having to Escape Quotes
How to Convert Milliseconds to "Hh:Mm:Ss" Format
What Is Short Circuiting and How Is It Used When Programming in Java
How to Find Unused/Dead Code in Java Projects
Overload with Different Return Type in Java
How to Escape Special HTML Characters in Jsp
Differencebetween "Class.Forname()" and "Class.Forname().Newinstance()"
What Is the Solution for the N+1 Issue in JPA and Hibernate
Swingpropertychangesupport to Dynamically Update Jtextarea
What Is the Equivalent Lambda Expression for System.Out::Println
How to Store Date/Time and Timestamps in Utc Time Zone with JPA and Hibernate
Why Do These Two Multiplication Operations Give Different Results
Spring Resttemplate - How to Enable Full Debugging/Logging of Requests/Responses