THE Java™ Programming Language, Fourth Edition

(Jeff_L) #1

12.9.1. State Assertions


Some assertions are used to test that the current state is always as it should be.


public void setEnds(Point p1, Point p2) {
this.p1 = p1;
this.p2 = p2;
distance = calculateDistance(p1, p2);
assert (distance >= 0) : "Negative distance";
}


In the above code, setting the endpoints causes the distance field to be recalculated. The distance calculation
should always result in a positive value. Any bug that gives distance a negative value would produce odd
effects when the value is used in the future. The assertion shown will catch such a bug right at the source.
Simple assertions of this form can be used in many places to ensure the sanity of your state and algorithms.


The terms precondition and postcondition refer to particular kinds of state assertion. A precondition is
something that must be true before a particular chunk of code (usually a method) is executed; a postcondition
must be true after. You can use assert to check pre- and postconditions, such as:


public boolean remove(Object value) {
assert count >= 0;
if (value == null)
throw new NullPointerException("value");
int orig = count;
boolean foundIt = false;
try {
// remove element from list (if it's there)
return foundIt;
} finally {
assert ((!foundIt && count == orig) ||
count == orig - 1);
}
}


Here the method enforces the precondition that the list size must be non-negative before the operation, and the
postcondition that the list size should be reduced by one after removal of an element, unless the element was
not in the list.


Note that the check for whether the element to remove is null is not an assert, but instead throws a
NullPointerException. In general you should expect that users of your class will make mistakes, and
so, where possible, you should always check for them and have defined what happens for when they make
them, such as returning a flag value or throwing an exception. In effect an assertion is a way of checking that
there are no bugs or unexpected usage in the code, not that the code that calls it is bug freeso do not use
assertions to validate arguments passed to your non-private methods.


Assert statements may or may not be executed, so the compiler will not always consider them reachable. A
variable that is initialized only in an assert statement will be considered potentially uninitialized because if
asserts are disabled it will be uninitialized. This will be true even if all uses of the variable are in other assert
statements.

Free download pdf