Conditional operators && and || are similar to their counterpart logical operators & and |, except that their evaluation is short-circuited. Given that x and y represent values of boolean expressions, the conditional operators are defined in Table 3.12. In the table, the operators are listed in decreasing precedence order.
Conditional AND | x && y | true if both operands are true; otherwise, false. |
Conditional OR | x || y | true if either or both operands are true; otherwise, false. |
Unlike their logical counterparts & and |, which can also be applied to integral operands for bitwise operations, the conditional operators && and || can only be applied to boolean operands. Their evaluation results in a boolean value. Truth-values for conditional operators are shown in Table 3.13. Not surprisingly, they have the same truth-values as their counterpart logical operators.
Note that, unlike their logical counterparts, there are no compound assignment operators for the conditional operators.
x | y | x && y | x || y |
---|---|---|---|
true | true | true | true |
true | false | false | true |
false | true | false | true |
false | false | false | false |
In evaluation of boolean expressions involving conditional AND and OR, the left-hand operand is evaluated before the right one, and the evaluation is short-circuited (i.e., if the result of the boolean expression can be determined from the left-hand operand, the right-hand operand is not evaluated). In other words, the right-hand operand is evaluated conditionally.
The binary conditional operators have precedence lower than either arithmetic, relational, or logical operators, but higher than assignment operators. The following examples illustrate usage of conditional operators:
boolean b1 = 4 == 2 && 1 < 4; // false, short-circuit evaluated as // (b1 = ((4 == 2) && (1 < 4))) boolean b2 = !b1 || 2.5 > 8; // true, short-circuit evaluated as // (b2 = ((!b1) || (2.5 > 8))) boolean b3 = !(b1 && b2); // true boolean b4 = b1 || !b3 && b2; // false, short-circuit evaluated as // (b4 = (b1 || ((!b3) && b2)))
Order of evaluation for computing the value of boolean variable b4 proceeds as follows:
(b4 = (b1 || ((!b3) && b2))) (b4 = (false || ((!b3) && b2))) (b4 = (false || ((!true) && b2))) (b4 = (false || ((false) && b2))) (b4 = (false || false)) (b4 = false)
Note that b2 is not evaluated, short-circuiting the evaluation.
Short-circuit evaluation can be used to ensure that a reference variable denotes an object before it is used.
if (objRef != null && objRef.doIt()) { /*...*/ }
The method call is now conditionally dependent on the left-hand operand and will not be executed if the variable objRef has the null reference. If we use the logical & operator and the variable objRef has the null reference, evaluation of the right-hand operand will cause a NullPointerException.
In summary, we employ the conditional operators && and || if the evaluation of the right-hand operand is conditionally dependent on the left-hand operand. We use the logical operators & and | if both operands must be evaluated. The subtlety of conditional operators is illustrated by the following examples:
if (i > 0 && i++ < 10) {/*...*/} // i is not incremented if i > 0 is false. if (i > 0 || i++ < 10) {/*...*/} // i is not incremented if i > 0 is true.