Reputation: 11808
This ugly piece of code does compile but throws NPE if s == null
public static boolean isNullOrEmpty(String s)
{
return s != null ? s.isEmpty() : null;
}
while this does not (as expected):
public static boolean isNullOrEmpty(String s)
{
if(s != null)
return s.isEmpty();
else
return null;
}
I know both of them are plainly wrong, but as I found the first piece of code in our sources, I was quite surprised it did compile.
Edit: Here's the relevant part of the JLS from Java 7. I guessed the first statement would apply but the bold one does.
15.25 Conditional Operator ? :
[...]
The type of a conditional expression is determined as follows:
[...]
[...]
Upvotes: 18
Views: 1872
Reputation: 178461
The first has a ternary operator which has a result type of Boolean
. The NPE is converting a null
to a boolean
.
It is actually something like:
Boolean temp = s != null ? s.isEmpty() : null; //no problems here
return temp; //crash when temp==null
The second is trying to return a wrong type (Object instead of primitive) - and thus does not compile.
Upvotes: 16
Reputation: 22181
Ternary Operator needs to find out the most appropriate return type for both operands.
Thus, it allows some "polish" of the return type.
As showed in your first code snippet:
public static boolean isNullOrEmpty(String s)
{
return s != null ? s.isEmpty() : null;
}
s.empty()
returns primitive boolean
whereas third operand returns null
.
So the most specific common return type is Boolean
. Compiler job is like replace the line by:
return s != null ? s.isEmpty() : (Boolean)null;
Return type method expects a boolean
primitive, so the compiler says: "cool, I just have to unbox my result !". Unfortunately, null
isn't unboxable and leads to an ugly NPE.
With your second snippet:
public static boolean isNullOrEmpty(String s)
{
if(s != null)
return s.isEmpty();
else
return null;
}
No additional "polish" of pre-return type is made since compiler doesn't link both return statements in this code => might be a too hard job for it.
So, in this case, it is logical that the code doesn't even compile since null
is NOT associated to Boolean
! So, no kind of cast occurs.
To compile it, it should be written as:
public static boolean isNullOrEmpty(String s)
{
if(s != null)
return s.isEmpty();
else
return (Boolean)null;
}
But does not prevent the famous NPE to occur while attempting to unbox ;)
Upvotes: 0
Reputation: 41945
Similar to Tricky Ternary Operator in JAVA
The ternary operator does Autoboxing using rules as quoted in JLS:
This rule is necessary because the conditional operator (§15.25) applies boxing conversion to the types of its operands, and uses the result in further calculations.
The problem is with the Autoboxing in Java. The problem is due to second operand not thrid.
public static boolean isNullOrEmpty(String s)
{
return s != null ? null : null;
}
This code wont compile
Upvotes: 0