Developer

JDK 1.4 lets you 'assert' yourself when you debug

Assertion statements, which are geared specifically for debugging, are new to Java 1.4 and provide a means to test code logic. See why you may want to consider using them over the traditional methods, such as if-then-else statements.


The assertion is an amazing programming facility introduced in JDK 1.4 that helps you debug and maintain your Java code. Basically, an assertion is a statement in the Java programming language that enables you to test your assumptions about a program. Let's take a closer look at how you can put assertions to work.

Why use assertions?
An assertion is a statement that tests a condition, somewhat as an if statement does. When the condition is violated, it triggers an error so that you know where to revise the assumption. This is a facility to reduce the error chances, especially for those beyond expectations.

Why choose an assertion instead of traditional methods, such as if-then-else, switch-case-default, or try-catch? The assertion is specifically designed for debugging, while the other methods are used mainly for production. Assertions are a tool of testing whether your logic is correct rather than capturing uncontrollable exceptions.

Many developers say that assertions are the quickest and most effective way to debug. Compare the following code and you can see the difference:

If-then-else style:
if (i % 3 != 0) {
if (i < 0)
{
System.err.println("Error in Variable i");
return -1;
}
System.out.println("Change $"+i%3);


Assertion style:
if (i % 3 != 0) {
assert i > 0;
System.out.println("Change $"+i%3);
}


The previous two sections of code work almost identically. If the variable i is exceptionally smaller than zero, the first block of code signals Error in Variable i. The second case throws an assertion error indicating the line where the error occurred. Obviously, the assertion requires far fewer lines.

Use assertions in your code
There are three ways to use an assertion in your Java code. Table A provides an overview.
Table A
Syntax Example
assert Expression1; assert i%3==2;
assert Expression1 : Expression2; assert i%3==2 : "Wow, Error";
throw new AssertionError(Expression1); throw new AssertionError("Oh no");
Assertion syntax

The first approach is the simplest. This statement verifies the Boolean expression Expression1 and throws an AssertionError exception if it is false. Here's an example:
Exception in thread "main" java.lang.AssertionError at TestAssert.main(TestAssert.java:8)

The prompt tells you the line where the assertion error occurred, so you can access the line and fix the bug.

The second approach provides more detail about the error. It verifies the Boolean expression Expression1 and throws an AssertionError exception to display the value of Expression2 if Expression1 is false. Here's an example of the exception display:
Exception in thread "main" java.lang.AssertionError: -1 at TestAssert.main(TestAssert.java:9)

This prompt tells you the line where the error occurred and includes the value, -1, displayed for the occurrence of the error. This can provide much more debugging information than the first approach.

The third method is a typical exception usage. You can use it when you want to raise an assertion exception manually.

After you insert assertion statements into your code, you compile and run your code, but the approach is different. The following command-line statement is used to compile when using assertions:
javac -source 1.4 MyCode.java

The -source option forces the compiled code to provide source compatibility with the specified release (1.4). This is necessary because assertions are new in JDK 1.4. The following command is used to run the program after compiling it with the compatibility of the release 1.4.
java -ea MyCode

The -ea option tells the system to enable the assertion feature during program execution. The program will not show the assertion exception message if you omit this option.

If you want to enable the assertion just in a specified package, such as com.lawrence.teki.chan, you can include the package after the -ea option:
java -ea:com.lawrence.teki.chan MyCode

Remember that the assertion is not a replacement for if-then-else or other syntax. The assertion is an effective facility for debugging programs and revises your algorithm.

Guidelines for using assertions
Since the assertion should be considered as a facility for verifying your program instead of a part of your program, you should follow these recommendations.

First of all, it is not a good idea to use the assertion argument checking in public methods, because argument checking is typically part of a contract and should be performed regardless of whether the assertion is enabled. When an error occurs, you should throw the appropriate runtime exception, such as IndexOutOfBoundsException or NullPointerException, instead of a general assertion error.

Second, it is not recommended to use assertions with a required operation. Since the assertion can be enabled or disabled, you should not mix the operation with the assertion. The assertion is just a tool for debugging. For instance, you may see the trouble in the following example:
assert names.remove(null);

names.remove(null) is supposed to be a valid statement in your program and is always expected to return true under your algorithm. If you want to check it by the assertion, it works, but the statement is skipped when the assertion is disabled. Therefore, you should separate the assertion from your correct operation, like this:
boolean nullsRemoved = names.remove(null);
assert nullsRemoved;


The second statement checks the returned value if the assertion is enabled, and the first sentence always invokes the operation names.remove(null). This ensures that the assertion does not affect the correct operation even if it is doable.

Although you may want to strip the assertions out of the final product, there is no tool that automatically erases assertion statements when no longer needed. But the following approach may help skip an assertion statement during compilation:
static final boolean isAssertUsed = true;
if (isAssertUsed) assert MyCondition;


This replaces the one-line statement, assert MyCondition. It triggers the assertion when isAssertUsed is true. When you do not need the assertion during compilation, change the value of isAssertUsed to be false:
static final boolean isAssertUsed = false;
if (isAssertUsed) assert MyCondition;


Since the condition isAssertUsed is always false, the content inside the if-blanket is an unreadable section, and the compiler will automatically skip the inside. This is called conditional compilation. The production version of your program will no longer include the assertion after you recompile the code with the above changes.

It is also recommended that you check whether the assertion is enabled before initializing a class. The following code may help you prevent a class from being initialized if the assertion has been disabled:
static {
boolean isAssertEnabled = false;
assert isAssertEnabled = true;
if (!isAssertEnabled)
throw new RuntimeException("Assertion must be enabled!");
}


The statement assert isAssertEnabled = true can set the variable isAssertEnabled to be true when the assertion is enabled. This statement is skipped (the variable remains false) when the assertion is disabled. So if the assertion is disabled, it will run the if-blanket statement and throw the exception.

Great method to verify logic
The assertion is a valuable debugging tool. It provides a clear and traceable form to verify program logic. It also provides a flexible and independent strategy that you can use in development, but that will be removed in production.

Editor's Picks