Working with Assertions

The Java 2 Platform, Standard Edition (J2SE) provides an assertion facility. Introduced with the 1.4 version of J2SE, one can think of the assertion facility as an advanced form of exception handling. Assertions represent are boolean expressions that a programmer believes to be true at specific points in the program. Is variable anInt greater than 2, for instance. The facility to check an assertion can be enabled or disabled at any time, so you might test the application with them enabled, and deploy with them disabled.

Assertion checking is like exception handling, but no exceptions are thrown if assertions fail. Instead, an AssertionError is thrown, and no try-catch block is necessary.

There are two basic constructs when using assertions:

assert booleanExpression;
assert booleanExpression : message;

You might add an assertion statement as the pre- or post-condition of a method. The boolean expression may also call a method. Other obvious places are else conditions in if blocks, where conditions are assumed, or 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. It can’t be with class variable declarations for instance, but can be within any method declaration.

Using assertions to compile and run your programs requires the use of some special command line options. To compile your program, you must pass the compiler a -source 1.4 setting. By default, the compiler runs in 1.3 compatibility mode. You must explicitly request the 1.4 source mode. Then, at runtime, you must explicitly enable assertion checking with the enableassertions option, or the shorter –ea option, as by default assertion checking is disabled.

Here’s a simple example that walks you through the necessary steps. 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);
}
}

To compile the program, be sure to use the -source option. javac -source 1.4 AssertTest.java

To test the program, just run the program and pass command line arguments:

java -ea AssertTest 1 2 3 4

This will report 4 since assert checking at runtime is disabled by default.

Now, if you run the program with assertion checking enabled, you’ll see the error message:

java -ea AssertTest 1 2 3 4

Reports the following problem:

Exception in thread "main" java.lang.AssertionError: 4 != 0
at AssertTest.main(AssertTest.java:3)

Essentially, that is the whole assertion facility. The hardest part is figuring out where to put the assert keywords.

While the -ea option is an easy way to enable assertions for an entire program, there are other options 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 (the package and all subpackages), you can follow the -ea option with a colon, the name of the package, and an ellipsis. For instance, the following will enable assertion checking for the net.java.util package, and all its subpackages.

java –ea:net.java.util... MyJava

For a specific class, you would just specify the full class name, instead of ending the package name with the three periods.

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. Just list the enabling and disabling options and you’re all set. For instance, the following enables assertion checking for the net.java.util package, but not the net.java.util.Math class.


java –ea:net.java.util... –da:net.java.util.Math MyClass

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 this isn’t something that can be just turned on and off at will.

The ClassLoader of the class controls the enabling and disabling of assertions through the following four methods:


setDefaultAssertionStatus()

This 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.


setPackageAssertionStatus()

To override the status for a package and all its subpackages, pass in the package name and enabling status. Providing a null package name sets the assertion status for the unnamed package.


setClassAssertionStatus()

To override the status for a specific class, pass in the fully-qualified class name and enabling status.


clearAssertionStatus()

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. In a non-static method, this would be done with the following:


ClassLoader loader = getClass().getClassLoader();

For a static method, you can’t call getClass() as you don’t have an instance, so you just add .class to the end of your current class name:


ClassLoader loader = MyClass.class.getClassLoader();

Just remember that this only has an effect on classes loaded after the change. In most cases, you’ll find yourself just enabling things from the command line.

What’s left with assertion checking? Just learning where to put them, really. This just takes practice. If you want to watch for special cases that typically shouldn’t happen and don’t overload code with if-blocks, assertion checking is a good way to go. Just don’t overuse them as it does bulk of the .class file sizes.

This entry was posted in Web Site Stuff. Bookmark the permalink.