Augmenting Java with Assertions

author-image
CIOL Bureau
Updated On
New Update

Kunal Jaggi

Advertisment

The Object Oriented paradigm is influenced by the design by contract principal, wherein, the creator and the consumer mutually agree to follow certain rules. The design by contract theory states that an application is created or designed according to a contract or specification agreed upon by the creator and the consumer about the functioning of the application. Assertions provide a mechanism for implementing the design-by-contract principal.

Assertions were introduced in early programming language like Eiffel and has been around since 1967. Assertions are not new to Java either. They were a part of Oak, an early version of JPL (Java Programming Language), but were dropped from the final draft.

What are Assertions?
Put simply, Assertions are a facility provided within the Java programming language to test the correctness or assumptions made by your program.
An assertion checks a Boolean-typed expression that a developer specifically proclaims must be true during program runtime execution. An assertion has a Boolean expression that, if false, indicates a bug in the code. The checks could be for assumptions about numbers being negative or being within or outside a certain range. Assertions are the outcome of JSR 41, and allow programmers to describe intended program behavior, which can be checked at runtime to detect bugs.

Advertisment
Applies To: Java SE developers
USP:
Debug Java applications and follow contract-by-design pattern
Primary Link:
http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html  Google Keywords: Assertions, JSR 41

Assertions vs Exceptions
Many developers confuse Assertions with Exceptions. Although some argue that Java has a built-in exception-handling support, there is still a need to provide a second alternative for checking program behavior. Exceptions handle abnormal conditions arising in the course of the program; however, they do not guarantee smooth or correct execution of the program.

Assertions, on the other hand, help state scenarios that ensure that the program is running smoothly. In fact, assertions are not supposed to replace exception handling but augment them. However at runtime, Assertions behave much like exception handling. When an assertion fails, the program would throw an AssertionError on to the stack trace. Another difference between Assertions and Exceptions is that Assertions are 'Errors'. The AssertionError class extends from the Error class.

Advertisment

Therefore, Assertions are Errors and unlike Exceptions (checked exceptions), they don't need to be wrapped in a try-catch block. Further, Assertions are flexible, they can be easily turned on and off by passing some command-line options. Exceptions define erroneous conditions which are predictable or reasonable enough for the program to catch and handle. Also, with Exceptions it is considered a good programming practice to catch more specific exceptions. An AssertionError, on the other hand, is very general, not very self-documentary or specific to the error condition.

The output (assertive program behavior) you get by running the same program while Assertions are disabled and enabled

Using Assertions
An assert statement has two permissible forms. The first one is:

Advertisment

assert expression1;

This statement tests the Boolean expression. It does nothing if the Boolean expression evaluates to true. However, if the Boolean expression evaluates to false, this statement throws an AssertionError.

The second form of the assert statement is quite similar to the first one, except one difference:

Advertisment

assert expression1 : expression2;

This form acts just like the first form. In addition, if the Boolean expression evaluates to false, the second expression is used as a detail message for the AssertionError. The second expression may be of any type except void. The second form adds flexibility, because it allows creating an overloaded form of AssertionError constructor, and dumping it on the stack trace.

Implementation
To demonstrate Assertions in Java, we'll look at an example of how a heating engine is designed by a statutory body, which adheres to all compliance. Then the design is passed on to a contractor for giving a practical shape to the laid norms. We'll assume that the heat level is set at 600 degrees Fahrenheit. Assertions can be made at the following stages:

Advertisment

Pre-condition: A condition that the caller of an operation agrees to satisfy. That is, pre-conditions are values or parameters passed to a method, to be used for the functioning of the program. The assert statements can be used to check the validity of the parameters passed before they get used in the body of the method. The following code snippet shows an assertive behavior.

abstract class HeatingEngine {
public final static double MAX_
TEMPERATURE = 600.0; //max limit

protected double heat_level;

Advertisment

public final void increase_temperature(double amt ) {
if( ( heat_level + amt ) > MAX_TEMPERATURE )
increase_temperatureImpl( MAX_TEMPERATURE - heat_level );
else
increase_temperatureImpl( amt );

assert ( heat_level <= MAX_TEMPERATURE ) : "Max Heating Level Overflow";
}
protected abstract void increase_temperatureImpl( double amt );

public final double getHeat_level() {
return this.heat_level;
}
}

Here, we set a pre-condition for the contractor to abide by the prescribed temperature limit. If this is violated, an AssertionError is propagated at runtime.

Post-condition: If the computation is successful, we say that the computation has satisfied the post-condition. A post-condition needs to be evaluated before each exit point in the method.

In our example, if the sum total of the passed parameter to the increase_temperature() method and existing heat level is below the permissible limit, the program flow enters in post-condition phase. The contract is implemented by a contracted, as shown in the following code fragment.

class EvilContractor extends HeatingEngine {
protected void increase_temperatureImpl( double amt ) {
this.heat_level = 1200.0;
}
}

It's pretty evident from the above code snippet that it is easy to breach the contract, as the contract can easily mutate on the values of inherited properties. Thanks to Assertions, such potential bugs can be caught early in the development cycle. The following code snippet shows the runtime calls to the methods carrying the application logic.

public class AssertDemo {
public static void main( String<> args ) {

HeatingEngine engine = new
EvilContractor();

// increasing the heating level to 100.0 Fahrenheit
engine.increase_temperature(100.0 );
System.out.println( "The current heat level is: " + engine.getHeat_level());
// increasing the heating level to 100.0 Fahrenheit
engine.increase_temperature(100.0 );
System.out.println( "The current heat level is: " + engine.getHeat_level());
}
}

Compile and run
Since Assertions is a new feature in Java SE 4, you need an SE 4 SDK to compile your assertion-friendly programs. Working with assertions is easy, assertive program behavior can be configured while running applications. To compile Java source code with assertion enabled, used the following command.

javac -source 1.4 AssertDemo.java

For backward compatibility, by default, assertions are disabled during runtime in the new JDK 1.4 runtime. Java allows you to enable assertions through a command line parameter –enableassertions or –ea during runtime, as shown below:

java –ea AssertDemo

Conclusion
As part of the Java Community Process, JSR (Java Specification Request) 41 proposed adding a simple assertion facility to Java SE Platform. Assertions can be used within programs to make sure the program behaves in a predetermined manner and will throw an error when violated.
An important thing to note about the assertion facility is that it is not provided as a user-level class library. Rather, it is built into the language by introducing a new keyword statement to JPL (Java Programming Language)-assert. Assertions are excellent for documenting assumptions and invariants about a class.

As a good programming practice, assert statements should not be used to check parameters of a public method. Also, Assertions must be disabled in production. Although you can, you must never attempt to catch an assertion error or any form of java.lang.Error.

Assertions are used to test programmer's assumption about a certain condition in the program. They give you a chance to catch errors during the program development and correct them to prevent serious programming errors from leaking into production code.

Source: PCQuest

tech-news