Java assert vs AssertionError

Posted by Grego on November 16, 2015

I’ve seen this question floating around a bit on the web so I thought I’d shed some light on the topic since it was bothering me for a little while also.

What’s the difference between assert and AssertionError?

People often ask what’s the difference between assert and manually throwing an AssertionError given that an assert statement will throw the AssertionError anyway?

Learning by Example

Let’s look at a super short example to paint a better picture:

/**
 * Example 1: assert statement, this is a totally goofy example but bear with me.
 */
public class Test {
    public static void main(String[] args) {
        assert false;
    }
}

Compile and run

javac Test.java && java Test

You may (or may not) be surprised to see no output. This is because java is ignoring your assertions. Simply re-run your application with assertions enabled, using the -ea switch:

java -ea Test
Exception in thread "main" java.lang.AssertionError
        at Test.main(Test.java:3)

Now let’s try throwing an AssertionError manually and see what happens:

/**
 * Example 2: Using AssertionError()
 */
public class Test {
    public static void main(String[] args) {
        throw new AssertionError();
    }
}

Build & run:

javac Test.java && java Test
Exception in thread "main" java.lang.AssertionError
        at Test.main(Test.java:3)

It seems like if we throw an AssertionError it guarantees that our program will crash. You might be wondering how that could possibly be a good thing, but first let me explain the semantics behind each.

Semantics: The Real Difference

The Java document Programming With Assertions states,

An assertion is a statement in the Java programming language that enables you to test your assumptions about your program.

It goes on to exemplify,

…if you write a method that calculates the speed of a particle, you might assert that the calculated speed is less than the speed of light.

While I’m not 100% sure about that science mambo-jambo, although it sound pretty legit to me I guess, the docs explain that assertions are intended to verify the assumptions that you make about your own code.

Each assertion contains a boolean expression that you believe will be true when the assertion executes. If it is not true, the system will throw an error. By verifying that the boolean expression is indeed true, the assertion confirms your assumptions about the behavior of your program, increasing your confidence that the program is free of errors.

Experience has shown that writing assertions while programming is one of the quickest and most effective ways to detect and correct bugs. As an added benefit, assertions serve to document the inner workings of your program, enhancing maintainability.

You can read the rest of their documentation about assertions (same link as above) if you’re interested to learn more about how to use them.

Manually throwing an AssertionError, by contrast, is making a statement to anyone using your code (including yourself) that one of the assumptions you have made about your code has been violated. In other words, you done goofed.

AssertionError is a subclass of Error. Which means we’ve hit an unrecoverable error and we shouldn’t try to catch it. The program is forced to crash as a metaphoric slap on the wrist to tell the developer they have screwed up and they need to mend their ways.

From the Error javadoc:

An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions

So it sounds like, semantically, we should throw an AssertionError whenever we see fit to tell the users of our code that they have attempted to use our code in a way it was not intended for.

Learning by Example, Revisited.

So wait… Why do we want our program to crash again?

Now like I said, it’s to protect the developers who are using our code (including ourselves) from doing something wrong with our code. Let’s look at some real-world examples where it might make sense to do this.

Let’s say you have a utility class with all static methods, you might want to enforce noninstantiability of a class by throwing such an error in the constructor:

// String utility class that does some common things with strings
public class MrStringUtility {
    // force non-instantiability through private method
    private MrStringUtility() {
        throw new AssertionError();
    }

    // ... some other string methods here
}

You may be wondering why is it an AssertionError and not an IllegalArgumentException. Throwing an Exception hints that we could just catch the exception and deal with it, which is not what we want. The last thing we need is people trying to forcibly use our code in ways it wasn’t designed and letting them get away with it — Oh-ho-ho!

In this example two steps are taken to prevent instantiation. The first is the use of the private visibility modifier (Josh Bloch, Item 4), this will prevent outside classes from accessing this constructor from conventional means. The second is the use of the AssertionError in the constructor which in itself serves two purposes: 1) it prevents instantiation of the class and 2) it signals to the troublemakers who have weaseled their way into this constructor that this class is not meant to be instantiated.

Another scenario in which you might want to see this in in a switch statement where you are fairly certain that there are only n possible options. Rather than omitting a default case, you can add one with an AssertionError().

public class MrRockPaperScissors {
    // assuming some enum has been defined for Rock, Paper, Scissors

    // outputs the winner of the game or some such
    public void determineWinner() {
        switch (playerChoice) {
            case Hand.Rock:
                // ...
                break;

            case Hand.Paper:
                // ...
                break;

            case Hand.Scissors:
                // ...
                break;

            default:
                throw new AssertionError();
        }
    }

    // ... some other code ...
}

Conclusion

So when is it really appropriate to use an AssertionError over a regular assert? An AssertionError as we’ve seen is more powerful than a regular assertion since it is guaranteed to explode, therefore it is more appropriate to use when we want to get a clear message across that something happened that should not be possible like instantiating classes that are not expected to be instantiated.