When Java sees a &&
operator or a
||
, the expression on the left side of the operator is
evaluated first. For example, consider the following:
boolean b, c, d;
b = !(3 > 2); // b is false
c = !(2 > 3); // c is true
d = b && c; // d is false
When Java evaluates the expression d = b &&
c;
, it first checks whether b
is true. Here
b
is false, so b && c
must be
false regardless of whether c
is or is not true, so
Java doesn't bother checking the value of c
.
On the other hand when faced with an ||
Java short
circuits the evaluation as soon as it encounters a true value since
the resulting expression must be true. This short circuit
evaluation is less important in Java than in C because in Java the
operands of &&
and ||
must be
booleans which are unlikely to have side effects that depend on
whether or not they are evaluated. Still it's possible to force
them. For instance consider this code.
boolean b = (n == 0) || (m/n > 2);
Even if n
is zero this line will never cause a
division by zero, because the left hand side is always evaluated
first. If n
is zero then the left hand side is true
and there's no need to evaluate the right hand side. Mathematically
this makes sense because m/0
is in some sense infinite
which is greater than two.
This isn't a perfect solution though because m
may
be 0 or it may be negative. If m
is negative and
n
is zero then m/n
is negative infinity
which is less than two. And if m
is also zero, then
m/n
is very undefined.
The proper solution at this point depends on your problem. Since real world quantities aren't infinite, when infinities start popping up in your programs, nine times out of ten it's a sign that you've lost too much precision. The remaining times are generally signals that you've left out some small factor in your physical model that would remove the infinity.
Therefore if there's a real chance your program will have a
divide by zero error think carefully about what it means and how
you should respond to it. If, upon reflection, you decide that what
you really want to know is whether m/n
is finite and
greater than zero you should use a line like this
boolean b = (n != 0) && (m/n > 0);
If you want all of your boolean expressions evaluated regardless of
the truth value of each, then you can use &
and
|
instead of &&
and
||
. However make sure you use these only on boolean
expressions. Unlike &&
and ||
,
&
and |
also have a meaning for
numeric types which is completely different from their meaning for
booleans.
Finally let's add the &&
, ||
,
&
, |
and ?
operators to
the precedence table