Java logical operator (&&, ||) short-circuit mechanism
Asked Answered
S

6

15

As I was reading a colleague's Java code, I stumbled upon an army of if/else statements. In these statements, several && and || operators were fighting each other without any help from parenthesis. I simplified the statements into:

if (true || true && false)
  return true;
else
  return false;

What do you think the result would be? Honestly, I thought it would be false, but it seems short-circuiting doesn't work like I expected. In this case, the result is true. The short-circuit mechanism seems to consider the whole expression as true when it finds true immediately followed by ||.

But in the reversed expression, what is the result?

if (false && true || true)
  return true;
else
  return false;

If we follow the same logic, it should be false. the first boolean is false and it is immediately followed by &&, but the result is true, once again. This makes sense to me, but it seems incompatible with our previous experiment.

So here's my theory:

If we find a true followed by ||, then it is true, no matter what might comes next, even if there is a long list of other logical operators coming after. But if we find a false followed by &&, it only short-circuits the next element, not the whole statement.

And here's my question:

Am I right? It seems a bit silly to me. Is true stronger than false?

Sedgemoor answered 4/5, 2015 at 14:44 Comment(9)
docs.oracle.com/javase/tutorial/java/nutsandbolts/… && has higher precedence than || as mentioned in existing answers (just wanted to provide the link)Upholstery
Anyway you should ask your colleague to write parenthesis in this case, to avoid errors that are likely to happen when someone will add a new condition in this code!Anglicanism
I think you are (partially) asking the wrong question. The correct question is: should one write such code like this; and the answer is: no, you should not.Disassemble
Short-circuting will never change the result of a boolean expression. The only thing short-circuting does is avoid executing the remainder of the expression.Skurnik
@Jägermeister, in fairness to the OP, if they'd asked whether the code should be written like that, the question would probably have been closed as being primarily opinion basedSound
it's not about short-circuit, it's about operator precedenceDialyze
One approach to avoiding confusion over precedence is to use parenthesis to clarify intent (which should be the first step), and then to place parenthesis (even when unnecessary) to clarify precedence, to help those who come later understand the meaning of the statement. As Java is compiled, the additional (and unnecessary) parenthesis only cost during compile time, and little even then.Orphaorphan
boolean algebra is really a basic topic for anyone who wants to write code. you should familiarize yourself thoroughly with it before approaching any programming language.Husk
Note that disjunction aka "or" is also called logical addition while conjunction aka "and" is called logical multiplication. Then the precedence comes out automatically.Shoelace
C
58

It's simply because

if (false && true || true)

is equivalent to (&& has a higher precedence)

if ((false && true) || true)

which is

if (false || true)

which is... true.

Note: In the expression true || true && false, the part true && false is called a dead code because it doesn't affect the final result of the evaluation, since true || anything is always true.


It is worth mentioning that there exist & and | operators that can be applied to booleans, they are much like && and || except that they don't short circuit, meaning that if you have the following expression:

if (someMethod() & anotherMethod())

and someMethod returns false, anotherMethod will still be reached! But the if won't be executed because the final result will be evaluated to false.

Cordi answered 4/5, 2015 at 14:46 Comment(15)
Alright, so it works like "1 + 1 * 2 = 3". I didn't know such a thing (the precedence), existed for the && and || operators. Thank you very much :)Sedgemoor
@JasonBerger false && true || true is very similar to 0 * 1 + 1, see Boolean Algebra for detailsHyperpituitarism
if (someMethod() & anotherMethod()) - Don't encourage writing code like this. That should be split into multiple lines.Parasitism
@BlueRaja-DannyPflughoeft I don't see anything wrong. Why not using it? It's there to be used. Experienced programmers should use it when they need to, it's clearer and sexier than splitting the condition.Cordi
If you actually want both methods to be executed (perhaps because they have side effects), they shouldn't be in an if. That's just incredibly confusing.Manhattan
@ChrisHayes I can give you many examples from real projects where it was very helpful and clear for me. At the end, it's a matter of personal taste. Again, it's there to be used.. Instead of saying "it's confusing" we should try to teach it and demonstrate its powers.Cordi
I'm willing to admit the possibility that it can be useful (though I'd have to see it to believe it), but "it's there to be used" is a very weak argument unless you think Java is a perfect language. Personally I consider the existence of these operators to be a flaw in Java.Manhattan
@ChrisHayes you're right, maybe "it's there to be used" is not a good explanation why it should be used.Cordi
To me it looks like a typo. And executing functions that set something in an if statement... no. No, no, no. Do you suppose it's okay if I overload = to trigger some business trigger in a statement like a=a;? It's there to be used too. (although it isn't available in Java.)Colorado
@Colorado No. & is there to be used how is supposed to, just like =. If it's look like a typo then you should get familiar with it.. Or simply not using it. However, it's weird to claim that it shouldn't be used because it looks like a typo.Cordi
& was designed for performing bitwise operations, not for chaining functions in if statements... it's just a side effect.Colorado
No.. It is well defined for boolean usage as well. It is implemented to this very specific usage.Cordi
Seeing you after long time :). Good answer. Plus 1.Infantilism
@JasonBerger every operator has precedenceAngular
@MarounMaroun: The most important thing is to make your code easy to read and understand, not "sexy". Trying to fit as many statements into one expression as possible was considered "cool" back in the C89 days, but nowadays it's just considered poorly-written and amateur-ish.Parasitism
I
15

The && has higher operation precedence over the ||, thus it wins.

Ibidem answered 4/5, 2015 at 14:46 Comment(0)
S
9

According to Java tutorials && has higher precedence over ||

So your true || true && false would be evaluated as true || (true && false)

And your false && true || true would be evaluated as (false && true) || true

Resulting in an output of true in both case.

Smearcase answered 4/5, 2015 at 14:53 Comment(0)
F
5

for &&:

false && ... => false

for ||:

true || ... => true.

And precedence for && is higher than ||.

See more: Operator Precedence in Java

Farley answered 4/5, 2015 at 14:51 Comment(0)
A
3

Because of the precedence of && on ||, (true || true && false) this will be evaluated as (true || (true && false)) -> (true || (false)) -> true

See the precedences rules: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html

Apostate answered 4/5, 2015 at 14:51 Comment(0)
B
1

I see what you were trying to do, but before operating on parentheses it's good to have the language's specification handy. I've known a few programmers who have gone so far as to keep the important bits, like operator precedence, on their walls.

The second part is to know whether your alterations are going to make any sense to the other people in your workplace; if removing parentheses compromises the meaning of an operation to someone else working on the code, then it could ultimately be detrimental.

The optimizer will generally take care of it for you, so when in doubt, leave them in there.

Boot answered 4/5, 2015 at 19:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.