Short circuiting logical operators, precedence, and evaluation order? [duplicate] - java

In JavaScript and Java, the equals operator (== or ===) has a higher precedence than the OR operator (||). Yet both languages (JS, Java) support short-circuiting in if statements:
When we have if(true || anything()), anything() isn't evaluated.
You can also have the following expression: true || foo == getValue()) - for example in an output statement such as console.log(...);, or in an assignment.
Now, according to operator precedence, short-circuiting shouldn't happen, as === = == > || in terms of precedence. (In other words, the comparison should happen first, for which getValue() ought to be called, as the equality check has a higher precedence that the OR comparison.) But it does. getValue() isn't called (as can easily be checked by putting an output statement into its body).
Why (does short circuiting work when the operator precedence says it shouldn't)?
Or am I confusing matters?

Or am I confusing matters?
You are. I think it's much simpler to think about precedence as grouping than ordering. It affects the order of evaluation, but only because it changes the grouping.
I don't know about Javascript for sure, but in Java operands are always evaluated in left-to-right order. The fact that == has higher precedence than || just means that
true || foo == getValue()
is evaluated as
true || (foo == getValue())
rather than
(true || foo) == getValue()
If you just think about precedence in that way, and then consider that evaluation is always left-to-right (so the left operand of || is always evaluated before the right operand, for example) then everything's simple - and getValue() is never evaluated due to short-circuiting.
To remove short-circuiting from the equation, consider this example instead:
A + B * C
... where A, B and C could just be variables, or they could be other expressions such as method calls. In Java, this is guaranteed to be evaluated as:
Evaluate A (and remember it for later)
Evaluate B
Evaluate C
Multiply the results of evaluating B and C
Add the result of evaluating A with the result of the multiplication
Note how even though * has higher precedence than +, A is still evaluated before either B or C. If you want to think of precedence in terms of ordering, note how the multiplication still happens before the addition - but it still fulfills the left-to-right evaluation order too.

According to the language specification, https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.24
At run time, the left-hand operand expression is evaluated first; if the result has type Boolean, it is subjected to unboxing conversion (§5.1.8).
If the resulting value is true, the value of the conditional-or expression is true and the right-hand operand expression is not evaluated.
So if you have a || b==c, it is not interpreted as (a || b) == c, because || has lower precedence, as you found in the tutorial. Instead, it is interpreted as a || (b==c). Now since a is the left side of ||, it is evaluated first.

There is no operator precedence in this case. What you are questioning is like in f(callback) statement the callback function being evaluated even before f. This can not happen.
On the other hand, in JS the || is one of the few places where you can watch laziness at show. The == operand (think as if it is an infix function like in fully functional languages) takes two arguments and the one on the left gets evaluated first. If it resolves to true the second argument doesn't even get evaluated.

Related

Execution order of f1() + f2()*f3() expression and operator precedence in JLS

Given an expression f1() + f2()*f3() with 3 method calls, java evaluates (operands of) addition operation first:
int result = f1() + f2()*f3();
f1 working
f2 working
f3 working
I (wrongly) expected f2() to be called first, then f3(), and finally f1(). Because multiplication shall be evaluated before addition.
So, I don't understand JLS here - what am I missing?
15.7.3. Evaluation Respects Parentheses and Precedence
The Java programming language respects the order of evaluation
indicated explicitly by parentheses and implicitly by operator
precedence.
How exactly operator precedence is respected in this example?
JLS mentions some exceptions in 15.7.5. Evaluation Order for Other Expressions (method invocation expressions (§15.12.4),method reference expressions (§15.13.3)), but I cannot apply any of those exceptions to my example.
I understand that JLS guarantees that operands of a binary operation are evaluated left-to-right. But in my example in order to understand method invocation sequence it is necessary to understand which operation (and both its operands respectively!) is considered first. Am I wrong here - why?
More examples:
int result = f1() + f2()*f3() + f4() + f5()*f6() + (f7()+f8());
proudly produces:
f1 working
f2 working
f3 working
f4 working
f5 working
f6 working
f7 working
f8 working
Which is 100% left-to-right, totally regardless of operator precedence.
int result = f1() + f2() + f3()*f4();
produces:
f1 working
f2 working
f3 working
f4 working
Here the compiler had two options:
f1()+f2() - addition first
f3()*f4() - multiplication first
But the "evaluate-left-to-right rule" works here as a charm!
This link implies that in such examples method calls are always evaluated left-to-right regardless of any parenthesis and associativity rules.
You're missing the text immediately under 15.7:
The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.
The values of the operands of an expression are evaluated before the expression itself. In your specific case, The outermost expression is f1() + [f2() * f3()]. We must first evaluate f1(), then we must evaluate f2() * f3(). Within that, f2() is evaluated first, then f3(), then the multiplication (which returns the value for the operand of the +).
JLS §15.17.2. Evaluate Operands before Operation:
The Java programming language guarantees that every operand of an
operator (except the conditional operators &&, ||, and ? :) appears to
be fully evaluated before any part ofthe operation itself is
performed.
Thus, f1(), f2() and f3() are evaluated first (left-to-right). Then, operator precedence is applied.
After all, you could observe the execution order in the bytecode, which in my case is:
[...]
INVOKESTATIC Main.f1 ()I
INVOKESTATIC Main.f2 ()I
INVOKESTATIC Main.f3 ()I
IMUL
IADD
Here is how the Expression Tree would look like:
+
/ \
/ \
f1 *
/ \
/ \
f2 f3
Leaves are evaluated first and the operator precedence is encoded in the tree itself.
Because multiplication shall be evaluated before addition.
As you seem to mean it, that's not a reasonable description of the precedence of multiplication over addition, nor of the effect of section 15.7.3. Precedence says that your expression
f1() + f2()*f3()
is evaluated the same as
f1() + (f2() * f3())
, as opposed to the same as
(f1() + f2()) * f3()
Precedence does not speak to which operand of the + operator is evaluated first, regardless of the nature of the operands. It speaks instead to what each operand is. This does impact order of evaluation, in that it follows from precedence rules that the result of the multiplication in your original expression must be computed before the result of the addition, but that does not speak directly to the question of when the values of two factors are evaluated relative to each other or to other sub-expressions.
Different rules than the one you quoted are responsible for the order in which the two operands of a + or * operator are evaluated -- always the left operand first and the right operand second.
How exactly operator precedence is respected in this example?
The example's output does not convey information about whether precedence -- understood correctly -- is respected. The same output would be observed for both of the two parenthesized alternatives above, and precedence is about which one of those two is equivalent to the original expression.
In an order-of-operations sense, precedence says (only) that the right-hand operand of the addition is f2()*f3(), which means that product must be computed before the overall sum can be. JLS 15.7.3 isn't saying anything more than or different from that. That that sub-expression is a multiplication has no bearing on its order of evaluation relative to the other operand of the addition operation.
I understand that JLS guarantees that operands of a binary operation are evaluated left-to-right. But in my example in order to
understand method invocation sequence it is necessary to understand
which operation (and both its operands respectively!) is considered
first. Am I wrong here - why?
Yes, you are wrong, and JLS notwithstanding, your examples provide very good evidence for that.
The problem seems to be the "and both its operands respectively" bit. Your idea seems to be roughly that Java should look through the expression, find all the multiplication operations and fully evaluate them, including their operands, and only afterward go back and do the same for the addition operations. But that is not required to observe precedence, and it is not consistent with the left-to-right evaluation order of addition operations, and it would make Java code much harder for humans to write or read.
Let's consider your longer example:
int result = f1() + f2()*f3() + f4() + f5()*f6() + (f7()+f8());
Evaluation proceeds as follows:
f1() is evaluated first, because it is the left operand of the first operation, and the the operation's operands must be evaluated left-to-right
f2() is evaluated next, because it is part of the right operand to the addition (whose turn it is to be evaluated), and specifically the left operand of the multiplication
f3() is evaluated next, because the multiplication sub-expression to which it belongs is being evaluated, and it is the right operand of that multiplication. Precedence affects the order of operations here by establishing that in fact it is the product that is being evaluated. If that were not so, then instead, the result of f2() would be added to the result of f1() at this point, before f3() was computed.
the product of f2() and f3() is computed, in accordance with the precedence of multiplication over addition.
The sum of (previously evaluated) f1() and f2()*f3() is computed. This arises from a combination of precedence of * over + already discussed, and the left-to-right associativity of +, which establishes that the sum is the left operand of the next addition operation, and therefore must be evaluated before that operation's right operand.
f4() is evaluated, because it is the right operand of the addition operation being evaluated at that point.
The second sum is computed. This is again because of the left-to-right associativity of +, and the left-to-right evaluation order of the next addition operation.
f5() then f6() then their product is evaluated. This is completely analogous to the case of f2()*f3(), and thus is another exercise of operator precedence.
the result of f5()*f6(), as the right-hand operand of an addition operation, is added to the left-hand operand. This is again analogous to previous steps.
f7() is evaluated.
Because of the parentheses, f8() is evaluated next, and then its sum with the previously-determined result of evaluating f7(), and then that result is added to the preceding result to complete the computation. Without the parentheses, the order would be different: the result of f7() would be added to the preceding result, then f8() computed, then that result added.
The most useful tip in my opinion was found in this discussion
JLS is not so clear on that - section 15.7 about evaluation speaks only about operands of a single operation, leaving unclear real-life complex cases with many operations combined.

Why does the "or" go before the "and"?

int it=9, at=9;
if(it>4 || ++at>10 && it>0)
{
System.out.print("stuff");
}
System.out.print(at);
prints out stuff9 and I want to know why as I thought ++at>10 && it>0 would be evaluated first and thus make at = 10.
Operator precedence only controls argument grouping; it has no effect on execution order. In almost all cases, the rules of Java say that statements are executed from left to right. The precedence of || and && causes the if control expression to be evaluated as
it>4 || (++at>10 && it>0)
but the higher precedence of && does not mean that the && gets evaluated first. Instead,
it>4
is evaluated, and since it's true, the short-circuit behavior of || means the right-hand side isn't evaluated at all.
Your compound expression is equivalent to
if(it>4 || (++at>10 && it>0))
due to Java operator precedence rules. The operands of || are evaluated left to right, so it>4 is evaluated first, which is true, so the rest of it (the entire && subexpression) doesn't need to be evaluated at all (and so at does not change).
I feel I should add how to actually get your expected output.
Brief explanation: the || operator short-circuits the entire expression, thus the right side not even being evaluated.
But, to not short-circuit and get your expected output, instead of the || operator, just use |, like so:
int a = 9, b = 9;
if(a>4 | ++b>10 && a>0)
{
System.out.print("stuff");
}
System.out.print(b);
The output to that is stuff10
This way, regardless of one side being true or not, they're both still evaluated.
The same thing goes for && and &

Does all evaluation happen from left to right?

String foo = null;
if(foo == null || foo.equals("")){
//this is only safe if I'm guaranteed that the evaluation happens from left to right
}
In Java, is there such a guarantee? Or do I need to perform these tests in tandem to be sure?
Yes. From JLS section 15.24:
The conditional-or operator || operator is like | (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is false.
The fact that the right-hand operand won't even be evaluated unless the left-hand operand is true means it has to be evaluated left-to-right... but in fact, that's the case for all operators. From JLS 15.7:
The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.
It's also true for method (and constructor) arguments. For example, from section 15.12.4.2 (Evaluate Arguments, part of Run-Time Evaluation of Method Invocation):
The argument expressions, if any, are evaluated in order, from left to right. If the evaluation of any argument expression completes abruptly, then no part of any argument expression to its right appears to have been evaluated, and the method invocation completes abruptly for the same reason.
(It's interesting to note the "appears to" here - it's okay for the JVM to actually evaluate them out-of-order, so long as that's not observable...)
The order is from left to right for ||, '&&'.
For || operator. If it sees if a||b, if a is false, it will check for b.
The || operator will short circuit if the left side is true. The left side is always evaluated first.
Yes, you are guaranteed that this code is safe: It will never throw a NullPointerException if foo is null.
FYI, your code fragment is typical for java code and is best practice.
Yes, java will short circuit a conditional with the OR operator from left to right.
At run time, the left-hand operand expression is evaluated first; if
the result has type Boolean, it is subjected to unboxing conversion
(§5.1.8).
If the resulting value is true, the value of the conditional-or
expression is true and the right-hand operand expression is not
evaluated.
If the value of the left-hand operand is false, then the right-hand
expression is evaluated; if the result has type Boolean, it is
subjected to unboxing conversion (§5.1.8). The resulting value becomes
the value of the conditional-or expression.
The answer is IT DEPENDS.
In your case - YES, but generally speaking it depends on the operator.
For example = (assign operator) evalutation is performed from right to left
int a = 1;
int b = 2;
int c = 3;
a = b = c;
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("c = " + c);
The result:
a = 3
b = 3
c = 3
Here you can find full list of Java operators and the order of evaluation: http://introcs.cs.princeton.edu/java/11precedence/
Your title is misleading. The answer to your actual question is 'yes', as per the JLS, but 'all evaluation happens from left to right' definitely isn't true.
This is a common misunderstanding. Consider the expression a+b*c. What the JLS actually says about evaluation order is that operands of an operator are evaluated left to right. So a,b,c are evaluated in that order, whatever they are, e.g. functions. The operators are applied according to the specified operator precedence (which isn't actually very well specified in the JLS). So of course the multiplication happens before the addition.

Bitwise operator and single ampersand [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why do we usually use || not |, what is the difference?
Can I use single ampersand like & instead of a bitwise operator like &&? What kind of differences may arise and is there a specific example to illustrate this issue clearly?
The single & will check both conditions always. The double && will stop after the first condition if it evaluates to false. Using two is a way of "short circuiting" the condition check if you truly only need 1 condition of 2 to be true or false.
An example could be:
if (myString != null && myString.equals("testing"))
If myString is null, the first condition would fail and it would not bother to check the value of it. This is one way you can avoid null pointers.
with & and ¦ both operands are always evaluated
with && and ¦¦ the second operand is only evaluated when it is necessary
Here's a link to a page with a pretty good explanation of how to use these.
Java Quick Reference on Operators
The other answers are correct to an extent, but don't explain the whole thing.
First off, the doubled operators, && and ||, function sort of like nested if statements:
if (expression_a && expression_b) {
do_something;
}
is equivalent to
if (expression_a) {
if (expression_b) {
do_something;
}
}
In both cases, if expression_a evaluates to false then expression_b will not be evaluated -- a feature referred to as "short-circuiting". (The || case is similar but a hair more complicated.)
Additionally, in Java (but not in C/C++) the && and || operators apply only to boolean values -- you cannot use && or || on an int, eg.
The single operators, & and |, on the other hand, are relatively "pure" operators (commutative and associative with respect to themselves), with none of the "short-circuiting" of the double operators. Additionally, they can operate on any integer type -- boolean, char, byte, short, int, long. They perform a bit-by-bit operation -- bit N of the left operand is ANDed or ORed with bit N of the right operand to produce the Nth bit in a result value that is the same bit width as the two operands (after they are widened as appropriate for binary operators). In this regard, their operation with boolean is just the degenerate case (albeit one that is somewhat special-cased).
Normally, one would use only the doubled operators for combining boolean expressions in an if statement. There is no great harm in using the single operators if the boolean expressions involved are "safe" (cannot result in a null pointer exception, eg), but the doubled operators tend to be slightly more efficient and the short-circuiting is often desired (as in if (a != null && a.b == 5), eg), so it's generally wise to cultivate the habit of using the doubled forms. The only thing to beware of is that if you want the second expression to be evaluated (for it's side-effects), the doubled operator will not guarantee this happens.

&& (AND) and || (OR) in IF statements

I have the following code:
if(!partialHits.get(req_nr).containsKey(z) || partialHits.get(req_nr).get(z) < tmpmap.get(z)){
partialHits.get(z).put(z, tmpmap.get(z));
}
where partialHits is a HashMap. What will happen if the first statement is true? Will Java still check the second statement? Because in order the first statement to be true, the HashMap should not contain the given key, so if the second statement is checked, I will get NullPointerException.
So in simple words, if we have the following code
if(a && b)
if(a || b)
would Java check b if a is false in the first case and if a is true in the second case?
No, it will not be evaluated. And this is very useful. For example, if you need to test whether a String is not null or empty, you can write:
if (str != null && !str.isEmpty()) {
doSomethingWith(str.charAt(0));
}
or, the other way around
if (str == null || str.isEmpty()) {
complainAboutUnusableString();
} else {
doSomethingWith(str.charAt(0));
}
If we didn't have 'short-circuits' in Java, we'd receive a lot of NullPointerExceptions in the above lines of code.
Java has 5 different boolean compare operators: &, &&, |, ||, ^
& and && are "and" operators, | and || "or" operators, ^ is "xor"
The single ones will check every parameter, regardless of the values, before checking the values of the parameters.
The double ones will first check the left parameter and its value and if true (||) or false (&&) leave the second one untouched.
Sound compilcated? An easy example should make it clear:
Given for all examples:
String aString = null;
AND:
if (aString != null & aString.equals("lala"))
Both parameters are checked before the evaluation is done and a NullPointerException will be thrown for the second parameter.
if (aString != null && aString.equals("lala"))
The first parameter is checked and it returns false, so the second paramter won't be checked, because the result is false anyway.
The same for OR:
if (aString == null | !aString.equals("lala"))
Will raise NullPointerException, too.
if (aString == null || !aString.equals("lala"))
The first parameter is checked and it returns true, so the second paramter won't be checked, because the result is true anyway.
XOR can't be optimized, because it depends on both parameters.
No it will not be checked. This behaviour is called short-circuit evaluation and is a feature in many languages including Java.
All the answers here are great but, just to illustrate where this comes from, for questions like this it's good to go to the source: the Java Language Specification.
Section 15:23, Conditional-And operator (&&), says:
The && operator is like & (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is true. [...] At run time, the left-hand operand expression is evaluated first [...] if the resulting value is false, the value of the conditional-and expression is false and the right-hand operand expression is not evaluated. If the value of the left-hand operand is true, then the right-hand expression is evaluated [...] the resulting value becomes the value of the conditional-and expression. Thus, && computes the same result as & on boolean operands. It differs only in that the right-hand operand expression is evaluated conditionally rather than always.
And similarly, Section 15:24, Conditional-Or operator (||), says:
The || operator is like | (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is false. [...] At run time, the left-hand operand expression is evaluated first; [...] if the resulting value is true, the value of the conditional-or expression is true and the right-hand operand expression is not evaluated. If the value of the left-hand operand is false, then the right-hand expression is evaluated; [...] the resulting value becomes the value of the conditional-or expression. Thus, || computes the same result as | on boolean or Boolean operands. It differs only in that the right-hand operand expression is evaluated conditionally rather than always.
A little repetitive, maybe, but the best confirmation of exactly how they work. Similarly the conditional operator (?:) only evaluates the appropriate 'half' (left half if the value is true, right half if it's false), allowing the use of expressions like:
int x = (y == null) ? 0 : y.getFoo();
without a NullPointerException.
Short circuit here means that the second condition won't be evaluated.
If ( A && B ) will result in short circuit if A is False.
If ( A && B ) will not result in short Circuit if A is True.
If ( A || B ) will result in short circuit if A is True.
If ( A || B ) will not result in short circuit if A is False.
No, if a is true (in a or test), b will not be tested, as the result of the test will always be true, whatever is the value of the b expression.
Make a simple test:
if (true || ((String) null).equals("foobar")) {
...
}
will not throw a NullPointerException!
No it won't, Java will short-circuit and stop evaluating once it knows the result.
Yes, the short-circuit evaluation for boolean expressions is the default behaviour in all the C-like family.
An interesting fact is that Java also uses the & and | as logic operands (they are overloaded, with int types they are the expected bitwise operations) to evaluate all the terms in the expression, which is also useful when you need the side-effects.
This goes back to the basic difference between & and &&, | and ||
BTW you perform the same tasks many times. Not sure if efficiency is an issue. You could remove some of the duplication.
Z z2 = partialHits.get(req_nr).get(z); // assuming a value cannout be null.
Z z3 = tmpmap.get(z); // assuming z3 cannot be null.
if(z2 == null || z2 < z3){
partialHits.get(z).put(z, z3);
}

Categories

Resources