Java boolean precedence comparation with ternary operator - java

I'd found a nice situation that I don't understand at all related to Java boolean operator precedence. I know and verify with the oracle official documentation here that && and || have precedence against ternary operator ? :
Now I have a weird line in my code similar to that
if (a.getItem() != null && a.getItem().getOtherItem() != null?true:a.getItem().getOtherItem().getSomevalue())
{
......
}
What I get, well, a nice java.lang.NullPointerException at a.getItem().getOtherItem() becouse a.getItem() is null. How I can solve it, encapsulate it between parenthesis
if (a.getItem() != null && (a.getItem().getOtherItem() != null?true:a.getItem().getOtherItem().getSomevalue()))
{
......
}
So my question is why I get a NullPointerException if I follow the Oficial Documentation previously linked && has precedence against ?: and && is short circuit evaluated (answered also here in some questions).

It seems you are confused about what “higher precedence” means. Let’s explain with a simple example:
The operator * has higher precedence than the operator '+'. This means that the expression a*b+c is evaluated like (a*b)+c. The same applies to the && operator and the ternary operator:
&& has higher precedence than the operator ? :. This means that the expression a&&b?c:d is evaluated as (a&&b)?c:d.
Hence the operator precedence works as documented in your example. It does exactly what you requested:
if (a.getItem() != null && a.getItem().getOtherItem() != null?
true:a.getItem().getOtherItem().getSomevalue())
If a.getItem() is not null and a.getItem().getOtherItem() is not null evaluate to true, otherwise to a.getItem().getOtherItem().getSomevalue(). So when either of the values is null, the code will attempt to evaluate the third term which will yield to a NullPointerException.
It’s not clear what you actually want to achieve. In your second example you say:
if (a.getItem() != null && (a.getItem().getOtherItem() != null?
true: a.getItem().getOtherItem().getSomevalue()))
so you want to interpret the case when a.getItem() is null as false but in the braced term you request to interpret the case when a.getItem().getOtherItem() is not null as true while the case that a.getItem().getOtherItem() is null should cause getSomevalue() to be called on the reference that you just have proven to be null.
What you most likely want to do is to evaluate a.getItem().getOtherItem().getSomevalue() if the all values are not null:
if (a.getItem() != null && a.getItem().getOtherItem() != null?
a.getItem().getOtherItem().getSomevalue(): false)
Note that you can express the same without the ternary operator at all. The equivalent statement would be:
if (a.getItem() != null && a.getItem().getOtherItem() != null
&& a.getItem().getOtherItem().getSomevalue())
In the case the fall-back value ought to be true like in
if (a.getItem() != null && a.getItem().getOtherItem() != null?
a.getItem().getOtherItem().getSomevalue(): true)
the same can be expressed as
if (a.getItem() == null || a.getItem().getOtherItem() == null
|| a.getItem().getOtherItem().getSomevalue())
Whenever you see true or false in a compound boolean expression you can be sure that there is something wrong.

The general use case for ? is to replace an if in a simple assignment branch, something like:
int a;
if(isOdd(b) || isPrime(b))
{
a = b;
}
else
{
a = -b;
}
into simply
int a = isOdd(b) || isPrime(b) ? b : -b;
And for this use case, it makes sense that && and || have precedence over ?.
The confusion arises only if ? returns boolean, the way you use it inside an if, which in my experience is very rare.

iI'd say that in your if statement
if (a.getItem() != null && a.getItem().getOtherItem() != null?true:a.getItem().getOtherItem().getSomevalue())
the following most inner part must be evaluated first
null?true:a.getItem().getOtherItem().getSomevalue()
so that the following part can be put together
if (a.getItem() != nulla.getItem().getOtherItem() !=<result_from_most_inner_part>)
In any case this if statement is ugly. Make the code rather readable and the compiler will do its part :P

Related

Error while attempting null check

I am checking for null before doing a certain operation but I have run into some issues. Following is the code:
if (c != null && c.size() != null) {
if (c.size() > 0) {
return (Application) c.toArray()[0];
}
I am getting a 'The operator != is undefined for the argument type(s)int, null' at the point
c.size() != null. I understand the return type for the size method is an integer, is that why I am getting this error? Hope someone can advise. Thank you.
int is a primitive type and is not an Object so is not a reference that can be null. Read more in this previous answer
Then in your code just remove that condition.
And also is preferred you use c.isEmpty() rather than c.size()>0
Your code would look like this:
if (c != null && !c.isEmpty()) {
return (Application) c.toArray()[0];
}
First of all, the result of c.size() is an integer. An int is a primitive, and it cannot be null. Only objects can be null.
Second, c.size() will never return null, so the check
c.size() != null
is unnecessary.
Note: There are wrapper classes for each primitive type. For example
Integer i = 4;
i = null; // valid
That assignment will be valid because i is an instance of the class Integer.

Validating BigDecimal data type for nulls In Java

I am trying to validate for NULLs on a data type BigDecimal in java. I am able to validate for 0 value however NULL's is resulting in a NULL Point Exception. Should I handle the validation of this datatype in an exception or is there some calculation I can preform on the data to validate it. Under is an example of what i have done so far:
if(crime.getCrimeLatLocation() != null & crime.getCrimeLongLocation() != null || crime.getCrimeLatLocation().compareTo(BigDecimal.ZERO) != 0 & crime.getCrimeLongLocation().compareTo(BigDecimal.ZERO) != 0){
logger.info('Valid Data');
}
Your || should be an && - what's happening is that when you pass in a null value it's evaluating to false in the first two conditions, but then it's proceeding on to the third and fourth conditions and resulting in an exception. If you change the || to an && then short circuit evaluation will prevent the third and fourth conditions from evaluating.
Be certain to use a && and not a & - the former uses short-circuit evaluation, but the latter would force the third and fourth conditions to evaluate and you'll get a null pointer exception again. condition1 && condition2 says "return false if condition1 is false, else evaluate condition2" - if condition1 is false then condition2 is never evaluated. In contrast, condition1 & condition2 will always evaluate both conditions. The only reason to use & is if the conditions have side-effects. Likewise, condition1 || condition2 will not evaluate condition2 if condition1 is true, but | will always evaluate both conditions.
Your test here
if(crime.getCrimeLatLocation() != null & crime.getCrimeLongLocation() != null
|| crime.getCrimeLatLocation().compareTo(BigDecimal.ZERO) != 0 & crime.getCrimeLongLocation().compareTo(BigDecimal.ZERO) != 0)
Uses binary not boolean operators, change this to
if((crime.getCrimeLatLocation() != null && crime.getCrimeLatLocation().compareTo(BigDecimal.ZERO) != 0)
|| (crime.getCrimeLongLocation() != null && crime.getCrimeLongLocation().compareTo(BigDecimal.ZERO) != 0))
This says that either crimeLatLocation is not null and not zero or crimeLongLocation is not null and not zero.
When you use & then both sides of the expression are evaluated, when you use && then the test is short circuited if the first part of the expression is false.
You need a check for null values before the comparison. You may use this function for the comparison.
/** This method compares 2 BigDecimal objects for equality. It takes care of null object and that was the necessity of having it.
* To use this function most efficiently pass the possibly null object before the not null object.
* #param pNumber1
* #param pNumber2
* #return boolean
*/
public static boolean isEqual(BigDecimal pNumber1, BigDecimal pNumber2)
{
if ( pNumber1 == null )
{
if ( pNumber2 == null)
return true;
return false;
}
if ( pNumber2 == null)
return false;
return pNumber1.compareTo(pNumber2)==0;
}
If your main goal is validating BigDecimal dataType for nulls, then just make a comparison;
yourBigDecimal != null.
The above statement is enough for comparison and checking.

The operator || is undefined for the argument type(s) java.lang.String, java.lang.String in Android app

I am trying to fetch database stored values and checking if ANY of the values exist then a method should be called.However, while checking I am getting this error--> The operator || is undefined for the argument type(s) java.lang.String, java.lang.String
if ((DBAdapter.KEY_AUDIENCE_TARGETING_COUNTRY
|| DBAdapter.KEY_AUDIENCE_TARGETING_WORLD) != null)
{
populate();
}
You miss the boolean expression in the first part of "if":
DBAdapter.KEY_AUDIENCE_TARGETING_COUNTRY and DBAdapter.KEY_AUDIENCE_TARGETING_WORLD are not boolean
You can use logical operators like ||, &&, etc. only with the boolean types.
Try comparing each value with "null" separately.
if(DBAdapter.KEY_AUDIENCE_TARGETING_COUNTRY != null || DBAdapter.KEY_AUDIENCE_TARGETING_WORLD != null)
{
populate();
}
In Java, you can use boolean operations only to booleans. Hope this helps.
Try:
if(DBAdapter.KEY_AUDIENCE_TARGETING_COUNTRY != null || DBAdapter.KEY_AUDIENCE_TARGETING_WORLD != null)
{
populate();
}
You can use logical operators like || and && only with the boolean values. As DBAdapter.KEY_AUDIENCE_TARGETING_COUNTRY and DBAdapter.KEY_AUDIENCE_TARGETING_WORLD are both Strings, Java doesn't know what to do with them when you add the || operator to it. You'll need to compare them to null individually.
If those are strings, you want to do this:
if (DBAdapter.KEY_AUDIENCE_TARGETING_COUNTRY != null ||
DBAdapter.KEY_AUDIENCE_TARGETING_WORLD != null)
{
// executes if at least one of the values is not null
}
You should use it like this.
if (DBAdapter.KEY_AUDIENCE_TARGETING_COUNTRY != null
|| DBAdapter.KEY_AUDIENCE_TARGETING_WORLD != null)
{
populate();
}
You can't use || when you use String. You can use this only for boolean values.
if((DBAdapter.KEY_AUDIENCE_TARGETING_COUNTRY ) || (DBAdapter.KEY_AUDIENCE_TARGETING_WORLD ))
{
populate();
}
Try this if it works

Variable can only be null shows eclipse

I have wriiten a method like this
public ArrayList<T> GetDoctorDetail(String name)
{
if (name!=null || !name.isEmpty() || name!="")
{
//Statements
}
}
but in eclipse !name by underline with a yellow line show
Null pointer access: The variable name can only be null at this location.
why? and what is the solution.
If name is non-null, the conditional || operator won't evaluate the second operand at all. So the only case in which the second operand can be evaluated is when name is null, in which case it will throw.
I suspect you want
if (name != null && !name.isEmpty())
{
// Use name
}
Or possibly:
if (name == null || name.isEmpty())
{
// Show an error message
}
Note that comparing strings with == and != is also almost always the wrong thing to do, as it compares references. You would normally use equals instead. Not only that, but it would be useless anyway here - it could only be equal to "" if it's empty, so it's the exact same condition as the second operand.
The first part of the oR condition will only fail if name = null. Hence the second part will throw a null pointer exception.
The correct way to write that condition is
if (name!=null && (!name.isEmpty() || name!=""))
if (name != null && !name.isEmpty()) {
// Now the name variable has valid content
}
Note - The logic is always much easier to understand if you create "positive" checks:
if (name == null || name.isEmpty()) {
// Now name is either null or empty
} else {
// Now the name has valid content
}
Try to avoid conditions that check for "negative" states, like "is not null" and "is not empty". They're nothing but brain twisters ;)

Java collapsible if statements

I use PMD to check my code. It gives me very useful hints in most cases, but I can't figure out what could be improved in the following scenario.
The original code looks something like this:
if ((getSomething() != null && getSomethingElse() != null)
|| (getSomething() == null && getSomethingElse() == null))
{
...
}
PMD tells me:
Sometimes two 'if' statements can be consolidated by separating their
conditions with a boolean short-circuit operator.
For simplicity, let's just use a and b as boolean variables. Then this piece of code looks like this:
if ((!a && !b) || (a && b))
This can be transformed to one of the following:
if ((!a || b) && (a || !b))
if (!(a^b))
and finally
if (a==b)
So I simplified my code to
if ((getSomething() == null) == (getSomethingElse() == null))
However, PMD keeps complaining (in fact about all three versions). Is this a false positive or is there a better way of writing the if-condition?
The problem was something different. The if-statement was the only code inside another if (the code comes from a validation-method):
if (...)
{
...
}
else if (...)
{
...
}
else if (...)
{
if ((getSomething() == null) == (getSomethingElse() == null))
{
...
}
}
What the PMD-message means, is that I could combine the conditions of the last else-if and the inner if-clause:
if (...)
{
...
}
else if (...)
{
...
}
else if (... && ((getSomething() == null) == (getSomethingElse() == null)))
{
...
}
However, I'm not sure, if I'll do this, because the original version seems much clearer to understand.
if ((a != null) && (b != null) && (a==b))
..although personally, I'd do the null checking prior to this if statement so I could handle the a == null and b == null cases individually
The issue is that large blocks of conditionals are difficult to reason about.
OTOH, not every warning PMD emits needs to be paid attention to--consider the ROI. Is it worth refactoring or restructuring to make it cleaner? Can the same functionality be handled in a different way?
If it's not worth it, don't bother.

Categories