if && had higher precedense, then first c2 would be printed.
15.22.2 Boolean Logical Operators &, ^, and |
When both operands of a &, ^, or | operator are of type boolean or Boolean, then
the type of the bitwise operator expression is boolean. In all cases, the operands
are subject to unboxing conversion (§5.1.8) as necessary.
For &, the result value is true if both operand values are true; otherwise, the result
For ^, the result value is true if the operand values are different; otherwise, the
result is false.
For |, the result value is false if both operand values are false; otherwise, the
result is true.
15.23 Conditional-And Operator &&
The conditional-and operator && is like & (§15.22.2), but evaluates its right-hand
operand only if the value of its left-hand operand is true.
15.24 Conditional-Or Operator ||
The conditional-or operator || operator is like | (§15.22.2), but evaluates its righthand
operand only if the value of its left-hand operand is false.
Jesse Silverman wrote:Trying not to think about it, my mind came up with this obvious example where we use parenthesis to override order of operations because floating point arithmetic is neither associative, commutative or distributive.
Mathematicians know that a * b / c is the same as a * (b / c) and a / c * b
Programmers know that they aren't:
jshell> float a = 2e30F
a ==> 2.0E30
jshell> float b = 3e30F
b ==> 3.0E30
jshell> float c = 4e30F
c ==> 4.0E30
jshell> a * b / c
$4 ==> Infinity
jshell> a * (b / c)
$5 ==> 1.5E30
jshell> a / c * b
$6 ==> 1.5E30
There are plenty of more subtle examples, but this one stands out as obvious.