Short-Circuiting
Sometimes, a boolean expression involving the &&
or ||
operator can be fully
evaluated without checking the second operand. In these situations, the computer
will skip evaluating the second operand, and this is called "short-circuiting".
When Do We Short-Circuit?
There are two situations where we can short-circuit a boolean expression:
- When we are ANDing two values (
&&
) and we see that the first value isfalse
, we don't need to check the second value to know that the result isfalse
. This is because an AND results infalse
unless both operands aretrue
. - When we are ORing two values (
||
) and we see that the first value istrue
, we don't need to check the second value to know that the result istrue
. This is because an OR results intrue
unless both operands arefalse
.
You can see this if you check the truth table
shown in the operators section. Both rows where a
is false
result in false
for a && b
, and both rows where a
is true
result in true
for a || b
.
You don't need to know what's in column b
in either of those situations to
tell me what's going to be in the column for &&
or ||
. This is why we can
"short-circuit" and skip looking in column b
.
On the other hand, if a
is true
, then you still need to check b
to
determine what's under a && b
, and if a
is false
, then you still need to
check b
to determine what's under a || b
. In these situations, we need to
evaluate b
before we know the result of the expression. This means we cannot
short-circuit.
Uses
Short-circuiting can be useful when we want to evaluate two boolean expressions, but one of them will cause an error in certain situations. For example, we're not allowed to divide integers by zero. If we want to divide two unknown integers, we need to make sure they aren't zero first:
int x = nextInt();
int y = nextInt();
if (y != 0) {
println(x / y);
} else {
println("We can't divide by zero!");
}
Let's say we want to know whether x / y
is an even number. We could write our
code like this:
int x = nextInt();
int y = nextInt();
if (y != 0) {
if ((x / y) % 2 == 0) {
println("x / y is even");
} else {
println("x / y is not even");
}
} else {
println("x / y is not even"); // if we can't divide x / y, then it's not even
}
However, that's long and repetitive. We can simplify this code by taking advantage of short-circuiting:
int x = nextInt();
int y = nextInt();
if (y != 0 && (x / y) % 2 == 0) {
println("x / y is even");
} else {
println("x / y is not even");
}
If the first part, y != 0
, is false, then y
is zero and dividing will
cause an error. However, if we have false
followed by &&
, then we don't need
to evaluate the part after the &&
to know that the &&
results in false
.
Java will use this fact to skip evaluating the (x / y) % 2 == 0
, and we won't
divide by zero and cause an error.
We can use ||
to ask the same question with short-circuiting if we change the
comparisons:
int x = nextInt();
int y = nextInt();
if (y == 0 || (x / y) % 2 != 0) {
println("x / y is not even");
} else {
println("x / y is even");
}