The Order of Evaluation of Logic Operators

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);

Avoiding Short Circuits

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.

Precedence

Finally let's add the &&, ||, &, | and ? operators to the precedence table

  1. *, /, % Multiplicative operators
  2. +, - Additive operators
  3. <, >, >=, <= Relational operators
  4. ==, != Then do any comparisons for equality and inequality
  5. & Bitwise and
  6. | Bitwise or
  7. && Logical and
  8. || Logical or
  9. ? : Conditional operator
  10. = Assignment operator

Previous | Next | Top | Cafe au Lait

Copyright 1997-1999 Elliotte Rusty Harold
elharo@metalab.unc.edu
Last Modified February 3, 1999