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.

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?

  1. 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.
  2. 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