Level: Introductory John Zukowski (jaz@zukowski.net), President, JZ Ventures, Inc.
01 Feb 2002 Merlin adds the ability to provide optional pre- and post-condition validation to methods for improved testing. Although the assertions facility is disabled by default at run time, it can be enabled to check error conditions. In this edition of Magic with Merlin, John Zukowski walks you through the basics of adding assertion checking to your code as well as enabling and disabling assertions, both from the command line and programmatically.
The assertion facility is one eagerly awaited new feature of the Java 1.4 release. You can think of this facility as an advanced form of exception handling. Assertions represent boolean expressions that the programmer
believes to be true at specific points in the program. For example, a programmer might include the assertion that you should never reach the default condition in a switch statement. Assertion validation can be enabled or disabled at any point in time, so it is possible to test with assertions enabled and deploy with them disabled. Likewise, an end user could re-enable assertions upon encountering a problem with the program in the field. In this column, I'll show you the basics of adding assertions to your code, demonstrating a couple of different ways to enable and disable them for optimum code testing and performance. The assert keyword
Assertion checking is like exception handling, but no exception is thrown when an assertion fails. Instead, an AssertionError is thrown. As with all errors, it is difficult if not impossible to
recover from an assertion failure, since such a failure indicates that program state has deviated from normal operating parameters. The two basic constructs for using assertions are as follows:
assert booleanExpression;
assert booleanExpression : message;
|
Note that the optional message would be shown as the result of an error thrown. You can add assertion statements as the pre- or post-conditions of a method. You can also set up the boolean expression to call a method. Likewise, you might want to add assertions to else conditions in if blocks, where conditions are assumed, or to default cases of a switch statement, which should never be reached. The only limitation of the assert keyword is that it must be in an executable block. An assertion cannot be used with class variable declarations for instance, but can be placed within any method.
Enabling assertions
If you want to use assertions, you'll have to use some special command-line options to compile and run your programs. Since the compiler runs in 1.3 compatibility mode, you'll have to explicitly request 1.4 mode.
To compile your program with assertions, simply pass the Java compiler a -source 1.4 setting. Assertion checking is disabled by default, so you'll also have to explicitly enable this facility at run time. Use the -enableassertions option, or the shorter -ea option, to enable assertion checking. The following simple example walks you through the necessary steps to add assertion checking to your program. It checks on the number of command-line arguments and reports a problem if the count isn't 0:
public class AssertTest {
public static void main(String args[]) {
assert args.length == 0 : args.length + " != 0";
System.out.println(args.length);
}
}
|
Be sure to use the -source option to compile the program,
as shown here:
javac -source 1.4 AssertTest.java
|
To test the program, just run the program and pass command-line arguments:
Because the program displays the count of arguments, this test will report four. Because assertion checking is disabled by default no assertion error is detected. Now, run the program with assertion checking enabled:
java -ea AssertTest 1 2 3 4
|
Running the program with assertion checking enabled produces the following error report:
Exception in thread "main" java.lang.AssertionError: 1 != 0
at AssertTest.main(AssertTest.java:3)
|
That is essentially the whole assertions facility. The hardest part is figuring out where to put the assert keywords and what the condition is.
More ways to work with assertions
While the -ea option is an easy way to enable assertions for an entire program, other options are available. Also, -ea doesn't work for system classes; for that, you need to
use -enablesystemassertions, or more easily, -esa. To enable assertions for an entire package tree (that is, the package and all subpackages), you would simply follow the -ea option with a colon, the name of the package, and an ellipses (...). For instance, the
following syntax will enable assertion checking for the net.zukowski.ibm package and all its subpackages:
java -ea:net.zukowski.ibm... EclipseTest
|
For a specific class, you would specify the full class name rather than ending the package name with the ellipses. If you want to enable assertion checking for a whole set of packages but not for a class or package (tree), that's where the -da tag comes into play ("-da" is short for -disableassertions). Just list the enabling and disabling options and you're all set. For instance,
the following syntax enables assertion checking for the net.zukowski.ibm package, but not the net.zukowski.ibm.BeanUtils class:
java -ea:net.zukowski.ibm... -da:net.zukowski.ibm.BeanUtils EclipseTest
|
Programmatically enabling assertions
In addition to enabling assertion checking from the command line, you can also programmatically enable (or disable) checking. This only affects classes loaded in the future, so it can't be turned on and off at will. The ClassLoader of the class controls the enabling and disabling of assertions with the following four methods:
-
public void setDefaultAssertionStatus(boolean enabled): This method sets the default status for packages and classes loaded by the class loader. This setting can be overwritten by setting the specific
package and class options.
-
public void setPackageAssertionStatus(String packageName, boolean enabled): To override the status for a package and all its subpackages, pass in the package name and enabling status.
-
public void setClassAssertionStatus(String className, boolean enabled): To override the status for a specific class, pass in the fully qualified class name and enabling status.
-
public void clearAssertionStatus(): This method resets all package and class settings to false, and then resets the class loader to setting false also.
To get the class loader for a class, call the getClassLoader() method of the Class object. Use the following command for a non-static method:
ClassLoader loader = getClass().getClassLoader();
|
For a static method, you can't call getClass(), because you don't have an instance, so you just add .class to the end of your current class name, as shown here:
ClassLoader loader = EclipseTest.class.getClassLoader();
|
Remember that this only affects classes loaded after the change. In most cases, you'll find yourself enabling assertions from the command line.
Wrapup
And there you have it. That's the Java 1.4 assertion facility. For tips on where to use assertions, see the Usage Notes section of the formal documentation pointed out in Resources. The key thing to remember when working with assertions is that they can be selectively enabled; therefore, they shouldn't have any side effects, short of timing differences.
Resources
About the author
Rate this page
|