Java Notes
Assertions
Assertions are used to stop execution when "impossible" situations are detected
Impossible conditions. Program debugging is filled with "impossible" problems ("But that parameter can't possibly be null"). If you're lucky, the problem is detected immediately in some way you can easily diagnose. If not, the error may propagate thru the program, finally crashing, but so far from the original bug that diagnosis is difficult. Even worse, the bug may not produce visible symptoms until after it has altered permanent data. Assert statements provide an easy means to check for impossible conditions, with little or no runtime cost.
Programmer, not user problems. The purpose or asserts is to detect programming errors, and they should not be used in the case of erroneous user input or actions.
Crash as quickly as possible. Discovering bugs as early as possible is good. Every program starts with bugs, and the debugging process is faster and simpler when the bugs are detected early. It's better to discover a problem at compile time than at run time, and it's better to discover a run-time bug as early as possible. Often a run-time bug doesn't cause an immediate, visible, disaster. Instead, the consequences of the bug distort the following execution, and the bad effects may not become visible for a long time. The crippled program may corrupt files or have other bad consequences. Tracing symptoms back to the original cause can be a long, tedious process. The goal is to detect bugs as early as possible. Assertions provide a relatively painless way to stop many bugs before they go too far.
Two forms of the assert
statement.
- Usual form
An assert statement has two parts separated by a colon. The boolean condition must be true for execution to continue. If it is false, an
AssertionError
is thrown, which terminates execution and display the message string. Some examples.assert jobQueue.size() == 0 : "processB: queue should have been empty."; assert connector != null : "merge: Connector null for " + rel;
When asserts are enabled (more on that below), the assert statement checks the condition (queue empty, connector is not null, etc) which must be true for the program to function correctly.. If it's true, execution continues. If it's null, an exception containing the message is thrown. This message is for the programmer, so it doesn't have to be user friendly. I typically include the name of the method and sometimes other information that will help make sense of the error.
- Abbreviated form
The simplest form the
assert
statement specifies only a boolean expression that must be true. This is OK when there's not much to say, or the likelihood of failing seems so remote it isn't worth the extra typing.assert n > 0;
How to figure out if assertions are turned on
Try this program to see if assertions are turned on.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/** flow-assertion/AssertTest.java - test assertions.
* @author Fred Swartz
* @version 1.01 2005-10-03
* Compile: javac AssertTest.java
* Run : java -ea AssertTest
*/
class AssertTest {
//=========================================================== main
public static void main(String[] args) {
// The following assert statement will stop execution
// with a message if assertions are turned on.
assert false : "Assertions are turned on.";
// The following statement will only be printed if
// assertions are turned off because assertions
// were not allowed at run time by the -ea parameter.
System.out.println("Assertions are not active.");
}
}
|
Test for consistency
One path to early bug detection is to test variables to see if they
have expected values. If something is wrong, the program can
stop and indicate that an unexpected inconsistency was discovered.
Later, when the program is released, this checking
may either be disabled to increase speed, or left in if a "crash" is better
than uncontrolled bug propagation (usually the case). If the checking code is removed or
disabled, it should be reinserted or activated during testing
all future updates. Writing checking code can be a major headache, so
it isn't done in many cases.
The assert
statement makes testing conditions relatively
easy, and allows easy activation or deactivation of some or all of the checking
code.
Check for "impossible" conditions, not bad input
assert
shouldn't be used for checking for bad input.
Input should
be checked by code that gives the user a meaningful response and
perhaps a chance to correct the input.
Assertions are used to check for things that can't possibly be wrong! This is what bugs are -- things that shouldn't happen do happen because there is something wrong with the code. Assertions are often used in the following cases.
- Check situations which must be true, but aren't obviously so. For example, the result of a complicated calculation must be in a certain range.
- All
switch
statements should havedefault
clauses. If this path is impossible, use an assert that will always fail.default: assert false: "You shouldn't be here!"
- Add an assert where control should never flow,
eg, when looking up and returning an entry that "must" be in
an array, the code after the loop should never be executed.
Put an
assert false: "some message"
there. - There is less of a need to check conditions which produce immediate
execution errors. For example, there is no need
to check if an array reference is null when the
array is used immediately after that, because
a NullPointerException would stop execution.
An
assert
would allow a better error message, and you must decide if the extra code is worth the better error diagnostic. In many cases the answer is "no".
Enabling assertions when running in NetBeans or TextPad
Assertion checking defaults to off at runtime, unfortunately. You should always turn them on.
See NetBeans 4.1 IDE for how to enable assertions. This also applies to the NetBeans 5 beta version.
See the TextPad Editor description for how to enable assertions.
Shouldn't runtime assertion checking default on?
- Some argue that a production program should not have the overhead of evaluating asserts. Asserts are not slow, but there is some cost. If they are not turned on at at execution time, the class loader actually strips out all the assertion code so they really don't take up any time or memory. But this small amount of time is surely unnoticeable in all but the most critical tasks.
- The user may be presented with an unfamiliar error message. This seems like an especially bad argument. Does the user really prefer bad results to a strange error message?
Why don't the same people that want assertion checking to default off also want subscript checking to default off?
Before Java 5
The assert
statement was added to
Java in version 1.4, but it didn't default on for the
compiler until version 5. You have to explicitly turn
it on in Java 1.4 by specifying the "-source 1.4" option
to the compiler.
See also
- Assertions in Java by Ranganath Kini