Incremental Java
Logical Operators

Starting Out

Logical operators work with boolean type expressions. You've seen boolean literals: true and false.

You can also declare variables with type boolean.

But how do you combine variables and literals together to create bigger expressions. Can you add two boolean values (no).

Java (and C/C++/C#) have support for logical operators. If you've ever taken a basic course in logic, you should already be familiar with the ideas behind Java logical operators.

Negation

The exclamation point is the unary negation operator. It looks like ! expr. expr must be a Boolean expression.

The result is to negate the Boolean value of the expression. If expr evaluates to true, then ! expr evaluates to false. If expr evaluates to false, then ! expr evaluates to true.

Here's a table that summarizes logical negation.

EVAL[ expr ] EVAL[ ! expr ]
true false
false true

Here, EVAL takes an expression and evaluates it (within an environment). Thus, the first column tells you that if the expression evaluates to some truth value, then negating it (the second column) evaluates to the negated truth value.

You often see negation used for condition variables. For example, you might have ! isRaining which stands for "it's not raining".

Logical AND (Conjunction)

Here's the standard truth table for logical AND.

exprleft exprright exprleft AND exprright
true true true
true false false
false true false
false false false

The entire expression evaluates to true only when both left and right subexpressions evaluate to true. Otherwise, the expression evaluates to false.

Short Circuiting

Java evaluates the left operand of a logical AND first, then the right operand. But notice what happens if the left operand is false. The entire expression is false regardless of what the right operand evaluates to.

If the left operand evaluates to false, Java doesn't evaluate the right operand. The entire evaluation is false. This kind of evaluation is called short-circuiting.

Normally, short-circuiting produces the same result as doing full evaluation. However, there are circumstances where the left operand is a kind of guard, and if the guard is false, it doesn't check the right operand.

For example, you may wish to perform a division, but you want to check if the denominator is not zero, so the division doesn't crash.

Such an expression might look like: denom != 0 && num / denom > 2. The left operand, denom != 0, checks to see if the denominator is not zero (!= checks to see if two values are NOT equal). If the left operand evaluates to false, it doesn't do the division in the right operand (nor the comparison).

If the left operand evaluates to true, then the right operand is evaluated, and the result of the two evaluations combined using logical AND using the truth table above. So short-circuiting only occurs when the left operand of a logical AND operator is false.

In Java, the logical AND operator is written as two ampersands, i.e., &&.

Here's the table, including short circuiting.

EVAL[ exprleft ] EVAL[ exprright ] EVAL[ exprleft && exprright ]
true true true
true false false
false not evaluated false
false not evaluated false

The last two rows indicate short circuiting.

Logical OR (Disjunction)

Here's the standard truth table for logical OR.

exprleft exprright exprleft OR exprright
true true true
true false true
false true true
false false false

The entire expression evaluates to false only when both left and right subexpression evaluate to false. Otherwise, the expressions evaluate to true.

Short Circuiting

Java evaluates the left operand of a logical AND first, then the right operand. But notice what happens if the left operand is true. The entire expression evaluates true regardless of what the right operand evaluates to.

If the left operand evaluates to true, Java doesn't evaluate the right operand. The entire evaluation is true.

This is short-circuiting for logical OR. We can use short-circuiting for logical OR in similar ways as short-circuiting for logical AND.

In Java, the logical OR operator is written as two vertical bars i.e., ||.

Here's the table, including short circuiting.

EVAL[ exprleft ] EVAL[ exprright ] EVAL[ exprleft || exprright ]
true not evaluated true
true not evaluated false
false true true
false false false

The first two rows indicate short circuiting.