Java Reference
In-Depth Information
java.lang.ArrayIndexOutOfBoundsException: 2
at Loop.thirdElementIsThree(Loop.java:19)
at Loop.main(Loop.java:13)
Clearly, there is a bug in the
thirdElementIsThree
method: It is throwing an
ArrayIndexOutOfBoundsException
. This exception was previously masquerading as the end of the
hideous exception-based loop.
The
thirdElementIsThree
method does return
TRue
if its argument has three or more elements and
the third element is equal to 3. The problem is what it does when these conditions do not hold. If
you look closely at the
boolean
expression whose value it returns, you'll see that it is a bit different
from most
boolean
AND operations. The expression is
a.length >= 3 & a[2] == 3
. Usually, you
see the
&&
operator used under these circumstances. This expression uses the
&
operator. Isn't that
the bitwise AND operator?
It turns out that the
&
operator has another meaning. In addition to its common use as the bitwise
AND operator for integral operands, it is overloaded to function as the
logical AND operator
when
applied to
boolean
operands [JLS 15.22.2]. This operator differs from the more commonly used
conditional AND operator
(
&&
) in that the
&
operator always evaluates both of its operands, whereas
the
&&
operator does not evaluate its right operand if its left operand evaluates to
false
[JLS 15.23].
Therefore, the
thirdElementIsThree
method attempts to access the third element of its array
argument even if it has fewer than three elements. Fixing this method is as simple as replacing the
&
operator with the
&&
operator. With this change, the program prints
2
as expected:
private static boolean thirdElementIsThree(int[] a) {
return a.length >= 3
&&
a[2] == 3;
}
Just as there is a logical AND operator to go with the more commonly used conditional AND
operator, there is a logical OR operator (
|
) to go with the conditional OR operator (
||
) [JLS
15.22.2, 15.24]. The
|
operator always evaluates both of its operands, whereas the
||
operator does
not evaluate its right operand if its left operand evaluates to
TRue
. It is easy to use the logical
operator rather than conditional operator by accident. Unfortunately, the compiler won't help you
find this error. Intentional uses of the logical operators are so rare that all uses are suspect; if you
really want to use one of these operators, make your intentions clear with a comment.
In summary, do not use the hideous loop idiom where an exception is used in preference to an
explicit termination test; this idiom is unclear, slow, and masks other bugs.
Be aware of the
existence of the logical AND and OR operators, and do not fall prey to unintentional use.
For
Search WWH ::
Custom Search