Post

Mastering AssertionError in Java with Hands-on Examples

In the grand complexity of the Java ecosystem, assertions stand as a small but mighty tool primarily employed for debugging and testing. Despite their minor recognition, they can have great value in enhancing the robustness of your code. Today, I am going to delve into a specific class known as AssertionError and shed light on how it works, when to use it, and precautions to take.

Understanding AssertionError

AssertionError is a subclass of Error that Java throws when an assertion fails. An assertion in Java is a statement or expression which your program expects to be always true. If the statement evaluates to false, JVM throws an AssertionError to indicate this unexpected discrepancy.

For instance, in a program that processes payments, we might assert that the payment balance is not a negative number because theoretically, it can never be.

1
2
3
4
5
6
7
public class Main {
   public static void main(String[] args) {
       double balance = -500.0;

       assert balance >= 0 : "Balance cannot be negative!";
   }
}

If the assertion validates false, running this program with assertion enabled (-ea flag) will throw an AssertionError.

1
Exception in thread "main" java.lang.AssertionError: Balance cannot be negative!

Proper Use of AssertionError

Assertions are not meant to replace error handling in your code but to serve as an extra line of defense for catching and diagnosing programming errors. They are to assist developers, not to handle normal program control flow or to manage user errors.

Assertions are disabled by default and need to be enabled during runtime. This is done because assertions could have a performance impact that we don’t want in the production code:

1
java -ea:com.mycompany... MyProgram

Do’s and Don’ts with AssertionError

In general, do not catch AssertionError in code. It is a subclass of Error not Exception, implying it is a serious problem that an application shouldn’t attempt to catch.

1
2
3
4
5
6
try {
   assert false;
}
catch (AssertionError e) {
   System.out.println("Caught an AssertionError." + e);
}

Avoid including application logic inside assertion checks. Since assertions can be disabled, any code inside assertion check may not get executed in production environment.

1
assert (++variable > 0); // Don't do this

Instead, increment variable outside the assertion check:

1
2
variable++; 
assert (variable > 0); // Do this

Using Custom AssertionError

You can create custom AssertionError where you can add more helpful debugging information when an assertion fails.

1
2
3
4
5
6
7
8
public class CustomAssertionError extends AssertionError {
    public CustomAssertionError(Object detail){
        super(String.valueOf(detail));
        if(detail == null){
            throw new NullPointerException();
        }
    }
}

Here, CustomAssertionError is an extension of AssertionError that provides more details when an assertion fails.

Best Practices with Assertions

  1. Assertions should not replace unit tests. Instead, they should go hand in hand.
  2. Assertions should not alter program state.
  3. Assertions should not be used for argument checking in public methods.
  4. Avoid catch blocks for AssertionError.
  5. Always provide informative assertion failure messages.

Conclusion

Assertions and AssertionError can act as a robust debugging tool if used properly, helping you catch programming errors right at the development and testing stages. However, remember not to overuse it in situations where traditional error handling methods should be used.

Adopt a balanced approach and employ assertions mainly for scenarios where failure would imply programming errors, and not for executing important code logic or dealing with user data.

References

  1. The Java™ Tutorials – Programming With Assertions
  2. Oracle Documentation - AssertionError
  3. JavaWorld – Understanding the AssertionError

Happy coding!

This post is licensed under CC BY 4.0 by the author.