#### Short-Circuit Evaluation

In the evaluation of boolean expressions involving conditional AND and OR, the left-hand operand is evaluated before the right-hand operand, 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 lower precedence than the arithmetic, relational, and logical operators, but higher precedence than the assignment operators.

Unboxing of the operand value takes place when necessary, before the operation is performed. 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)))

The order of evaluation for computing the value stored in the 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. Example 2.3 illustrates the short-circuit evaluation of the initialization expressions in the declaration statements given in the code snippet above. In addition, it shows an evaluation (see the declaration of b5) involving boolean logical operators that always evaluate both operands. The output shows how many operands were evaluated for each expression. See also Example 2.1, p. 53, which uses a similar approach to illustrate the order of operand evaluation in arithmetic expressions.

Example 2.3 Short-Circuit Evaluation Involving Conditional Operators

public class ShortCircuit {

public static void main(String[] args) {

// Boolean b1 = 4 == 2 && 1 < 4;

Boolean b1 = operandEval(1, 4 == 2) && operandEval(2, 1 < 4);

System.out.println(“Value of b1: ” + b1);

// boolean b2 = !b1 || 2.5 > 8;

boolean b2 = !operandEval(1, b1) || operandEval(2, 2.5 > 8);

System.out.println(“Value of b2: ” + b2);

// Boolean b3 = !(b1 && b2);

Boolean b3 = !(operandEval(1, b1) && operandEval(2, b2));

System.out.println(“Value of b3: ” + b3);

// boolean b4 = b1 || !b3 && b2;

boolean b4 = operandEval(1, b1) || !operandEval(2, b3) && operandEval(3, b2);

System.out.println(“Value of b4: ” + b4);

// boolean b5 = b1 | !b3 & b2; // Using boolean logical operators

boolean b5 = operandEval(1, b1) | !operandEval(2, b3) & operandEval(3, b2);

System.out.println(“Value of b5: ” + b5);

}

static boolean operandEval(int opNum, boolean operand) { // (1)

System.out.println(opNum);

return operand;

}

}

Output from the program:

1

Value of b1: false

1

Value of b2: true

1

Value of b3: true

1

2

Value of b4: false

1

2

3

Value of b5: false

Short-circuit evaluation can be used to ensure that a reference variable denotes an object before it is used.

if (objRef != null && objRef.equals(other)) { /*…*/ }

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 result in 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 boolean 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.