why unexpected behaviour for conditional operator - java

I have a piece of code like follows
public class Test{
public static void main(String[] args) {
System.out.println(true?false:true == true?false:true);
-----------------------
}
}
The output is false. If you are using Eclipse you get a wavy (dashed here) line and warning like "Comparing identical expressions". Note the start of the wavy line.
I changed the code to the following
public class Test{
public static void main(String[] args) {
System.out.println((true?false:true) == (true?false:true));
---------------------------------------
}
}
The output is true. If you are using Eclipse you get a wavy (dashed here) line and warning like "Comparing identical expressions". Note the start of the wavy line now.
Why the difference?

Because ternary operator (?:) has lower priority than equality operator (==). This means that:
true?false:true == true?false:true
is actually interpreted as:
true?false:(true == true?false:true)
This, in turns, is evaluated to:
true?false:((true == true)?false:true)
cont.:
true?false:(true?false:true)
...and eventually:
true?false:(false)
and eventually:
true?false:false
And obviously this explains the output of the first code snippet. Eclipse correctly recognizes operator precedence and highlights possibly incorrect statement.
UPDATE: Thanks for all the comments. In fact I forgot about operator precedence on the left side. I checked the exact behaviour using the program below:
public static boolean a(char label, boolean result) {
System.out.println(label);
return result;
}
public static void main(String[] args) {
System.out.println(
a('a', true) ? a('b', false) : a('c', true) == a('d', true) ? a('e', false) : a('f', true)
);
}
The results are consistent with #Milad Naseri suggestion.

There is nothing unexpected here, the answer is operator precedence.
In the first case it is:
true?false:(true == true?false:true)
While the in the second case your paretheses override the precedence rules.

In case your problem is the difference of outcomes, this is because of the order of precedence of the operators you use. Check here for details. According to that order of precedence:
true ? false : true == true ? false : true
is the same as this:
true ? false : ((true == true) ? false : true)
so it will always evaluate to false. You could put anything after the colon since it's never evaluated anyway (if I remember correctly and the ternary operator uses lazy evaluation); the reason for this is that
true ? A : B
always evaluates to A.
On the other hand,
(true ? false : true) == (true ? false : true)
will have both sides of the comparison operator == evaluate to false, so
false == false
which is a true statement.
So the difference here is the order in which the operators are evaluated, which is determined by the parentheses you use and, if there is ambiguity that isn't resolved by parentheses, by the order of precedence of the operators that are used.
In general, the ternary operator "? :" works like this
A ? B : C
If A is true, evaluate to B, else evaluate to C. A has to be a boolean expression, B and C can be whatever you want; you'll have to deal with type mismatches though if you want to assign the evaluated value to a variable and they are of different types.

That is because the conditional equality operator (==) takes precedence over the ternary conditional ?:. So, in a?b:x==y?z:t x==y?z:t is evaluated before a?b:x and y?z:t are.

Related

java how to change this code from finding all true objects to find false

I have code that finds all the objects in the list that are true to getranonelectricity and prints them out. How do I change this code so it finds and prints out only false ranonelectricity objects?
Transport transports[]=new Transport[10];
transports[0]=Transport1;
transports[1]=Transport2;
transports[2]=Transport3;
transports[3]=Transport3;
transports[4]=Transport4;
transports[5]=Transport5;
transports[6]=Transport6;
transports[7]=Transport7;
transports[8]=Transport8;
transports[9]=Transport9;
for (Transport transportssssss : transports) {
if (transportssssss instanceof car) {
if (((car) transportssssss).getranonelectricity()) {
System.out.println(transportssssss);
Change
if(((car) transportssssss).getranonelectricity()){
to
if(!((car) transportssssss).getranonelectricity()){
The ! operator will invert the truth value of any Boolean expression.
Please read about Logical Operators in Java. For example this: https://www.dummies.com/programming/java/logical-operators-in-java/
You need a "Not" operator.

Java Method while-looping endlessly even though breakout case seems to be met

I have a while loop whose loop condition is that a boolean variabke is true. The loop has logic in it to set the boolean variable to false when it's time to exit the loop. However, it never exits. I have confirmed by printing a message that the variable is being set to false.
Here is a précis of the method:
public void collapse(){
boolean status=true;
while(status=true){
// some processing
if (some condition) {
System.out.println("Setting status to false");
status = false;
}
// more processing that doesn't set status to true
}
}
What's going on here?
You're assigning status to true in the while statement, instead of checking for equality. Either change it to status == true, or you could just use status.
You have an assignment in your loop condition while(status=true).
To check the status just do while(status).
while(status==true){
Should be ==
= is used to asign
== is used for comparison
It's an anti-pattern to compare a boolean for this very reason - just evaluate it, ie change
while (status = true)
To
while (status)
Then it's easier to read, less code to write and has no chance of this kind of bug occurring.
This:
while(status=true)
should be:
while(status == true)
A single = is an assignment operator and == is a comparison operator.
You are using the assignment operator = when you want to use the boolean compare ==.
It should be:
while (status == true){
...
}

IntelliJ IDEA Reporting Contract Violation Warning

Here is the Java code:
public static boolean anyEqual(Object needle, Object... haystack) {
if(needle == null || haystack == null) {
return false;
}
if(haystack.length == 0) {
return false;
}
for(Object match : haystack) {
if(match != null && needle.getClass() == match.getClass() && needle.equals(match)) {
return true; // warning from IntelliJ here, 'contract clause !null, null -> false is violated'
}
}
return false;
}
Does anyone have any idea why this is being shown? contract clause !null, null -> false is violated? Thanks!
IntelliJ 14.0.2 build: 139.659
Screenshot:
IntelliJ is inferring the formal contract of your method to be this:
null, _ -> false; !null, null -> false
What this actually means:
The first contract specifies that, so long as the first parameter is null, it will return false. This is observed by your first if statement:
if(needle == null || haystack == null) {
return false;
}
The second contract specifies that, if the second parameter is null, then it will return false. This is also specified by the same if statement above.
My gut is telling me that IntelliJ is having some trouble discerning what the loop's formal contract is in addition to all of the above, although it'd be as simple as another condition in the contract expression.
for(Object match : haystack) {
if(match != null && needle.getClass() == match.getClass() && needle.equals(match)) {
return true;
}
}
Let's briefly go through this.
The enhanced-for statement won't fire if haystack is of length 0, so that's something to take into consideration.
The elements inside of the array could be null, and I'm not entirely sure that IntelliJ's static analysis covers that piece yet.
We've established already that needle must be non-null, so there's nothing violating the contract at that line.
If we have a scenario in which match != null && needle.getClass() == match.getClass() && needle.equals(match) is true, we return true. Otherwise, we return false.
There's nothing that I can see in the formal documentation that gives us the expression we require to say, "hey - we're checking elements of an array!"; it may be the case that the analysis is tripping up on the fact that we're returning true in spite of what we stated above (since haystack is non-null).
Allow me to stress this point:
haystack has to be non-null in order for you to enter into the enhanced-for. Your code will not work otherwise.
All in all, I wouldn't worry about it. Better yet, file a bug against it so that this sort of thing could be fixed or expanded upon.
This looks like an IntelliJ bug to me, since by removing the static keyword from the method the warning disappears.
Something must be confusing the static analysis here. One can always submit this to youtrack so jetbrains devs can look at it.
Someone already reported this issue Here
(tested on v14.0.3)
This message is being shown because IntelliJ checks for method contract violations. It's a relatively new feature, read more at https://www.jetbrains.com/idea/features/annotation_java.html

(!var) vs (var==null) in java / groovy

What is recommended in java :
if(!var){
}
or
if(var==null){
}
and why?
It is the same thing with Groovy?
In java, if var is null,
if( !var ) {
// var is not null
}
Won't work as ! is for booleans.
In Groovy, it will work as it applies Groovy Truth.
HOWEVER, if you are testing for null, then you should use the explicit test
if( var != null ) {
// var is not null
}
Even in Groovy, as if var was anything Groovy considers false, the first comparison would pass, ie:
assert !0
assert !''
assert ![]
assert !null
Of course you can also use the null safe operator:
def map = [ person:[ tim:[ login:'tim_yates' ] ] ]
assert map?.person?.tim?.login == 'tim_yates'
assert map?.person?.alice?.login == null
The first one in Java would apply only to booleans
The unary operator ! does the negation operation. For example,
!false will yield true.
And == does comparison operation.
They both are completely different to each other. In java, you can use the negation operator only with boolean values, whereas the comparison operator can be used to compare values.
Also, in Java, if var is Boolean and is null, then
if(!var){ // would throw a NullPointerException
}

Java Ternary Operator inside ternary operator, how evaluated?

Very basic question I suppose, I just wanted to know how this code is read:
return someboolean ? new someinstanceofsomething() : someotherboolean ? new otherinstance() : new third instance();
I guess now as I'm writing it I kind of understand the statement. It returns option one if true but then does another boolean check if false and returns one of the two remaining options? I'm going to continue to leave this question because I have not seen it before and maybe others have not as well.
Could you go on indefinitely with ternary inside of ternary operations?
Edit: Also why is this/is this not better for code than using a bunch of if statements?
It is defined in JLS #15.25:
The conditional operator is syntactically right-associative (it groups right-to-left). Thus, a?b:c?d:e?f:g means the same as a?b:(c?d:(e?f:g)).
In your case,
return someboolean ? new someinstanceofsomething() : someotherboolean ? new otherinstance() : new third instance();
is equivalent to:
return someboolean ? new someinstanceofsomething() : (someotherboolean ? new otherinstance() : new third instance());
Ternary operators are right-associative. See assylias's answer for the JLS reference.
Your example would translate to:
if (someboolean) {
return new someinstanceofsomething();
} else {
if (someotherboolean) {
return new otherinstance();
} else {
return new thirdinstance()
}
}
And yes, you can nest these indefinitely.

Categories