Java assert Keyword: Assertions with Examples

Learn the Java assert keyword, enabling assertions with -ea, AssertionError, when to use assert vs exceptions, side effects, and assertions in tests.

Flow of an assert statement with assertions disabled and enabled

The assert keyword checks a condition that the developer believes is always true, and throws an AssertionError when the condition is false and assertions are enabled. Assertions are disabled by default, so the JVM skips them entirely in a normal run and they cost nothing in production.

We use assertions to document and test internal assumptions, such as a loop invariant, a branch that should never run, or the state of an object after a private method. They catch bugs early during development and testing, and they are not a way to validate user input or method arguments.

The following example checks that a computed discount stays within its expected range.

static int discountedPrice(int price, int percent) {
    int discounted = price - price * percent / 100;
    assert discounted >= 0 && discounted <= price : "bad discount " + percent + "% on " + price;
    return discounted;
}
int sale = discountedPrice(200, 25);    // 150

Notice that a percent above 100 breaks the assumption. We run the program with and without assertions, look at both forms of the statement, the command-line switches, the rules for good assertions, and how assertions behave in unit tests.

1. Syntax of the assert Statement

The assert statement has two forms. The first form has only a boolean condition, and the second form adds a detail message after a colon, which becomes the message of the AssertionError.

Flow of an assert statement with assertions disabled and enabled
Disabled assertions skip the condition; enabled ones throw AssertionError when it is false
assert condition;
assert condition : detailMessage;

The detail expression can be any value, such as a String or a number, and it is evaluated only when the condition is false. A good message contains the values that broke the assumption, because the stack trace alone shows only the line.

2. Enabling and Disabling Assertions

Assertions run only when the JVM starts with the -ea switch; without it, the condition is never evaluated. The calls to discountedPrice(200, 150) show the difference.

$ java Shop.java
-100

$ java -ea Shop.java
Exception in thread "main" java.lang.AssertionError: bad discount 150% on 200
    at Shop.discountedPrice(Shop.java:4)

The switches can target the whole program, a package with its subpackages, or a single class. They are applied from left to right, so a later switch can override an earlier one.

SwitchEffect
-ea or -enableassertionsEnables assertions in all application classes
-da or -disableassertionsDisables assertions in all application classes, which is the default
-ea:com.shop…Enables assertions in the package com.shop and all its subpackages
-ea:com.shop.CartEnables assertions in one class
-ea -da:com.shop.CartEnables assertions everywhere except one class
-esa or -enablesystemassertionsEnables assertions in the JDK classes, which -ea does not cover

In IntelliJ IDEA and Eclipse, we add -ea to the VM options of the run configuration. Programs can also change the setting for classes that are not loaded yet with ClassLoader.setDefaultAssertionStatus() and the package and class variants of that method.

3. Assertions Are Skipped When Disabled

A disabled assert statement does not evaluate its condition at all. Any method called inside the condition is not called, so an assertion must never contain code that the program needs.

List<String> cart = new ArrayList<>(List.of("pen", "ink"));
String item = "pen";

// wrong: the item is removed only when assertions are enabled
assert cart.remove(item);

// right: the work happens always, only the check is optional
boolean removed = cart.remove(item);
assert removed : "item was not in the cart: " + item;

The same rule covers counters, logging and any other side effect. With assertions disabled, the first version leaves the item in the cart, which is a hard bug to find because it disappears as soon as a developer enables assertions to debug it.

4. When to Use assert in Java

The Oracle guide to assertions draws a clear line. Assertions check things that are under our own control and can only fail because of a bug in our code. Everything that can fail because of a caller or the outside world needs a normal check that always runs.

Use assert forUse an exception for
Invariants inside a class, such as a balance that is never negativeArguments of public methods, with Objects.requireNonNull() or IllegalArgumentException
Results of private helper methodsUser input, file content and network data
Branches that should never run, such as an impossible default caseMissing configuration or resources
Loop invariants in algorithmsAny condition the program must check in production

Public methods must check their arguments with exceptions, because the caller is outside our control and the check must also run in production. A private method can use assert for its arguments, because all its callers are in the same class.

static String quarterName(int month) {
    return switch ((month - 1) / 3) {
        case 0 -> "Q1";
        case 1 -> "Q2";
        case 2 -> "Q3";
        case 3 -> "Q4";
        default -> throw new AssertionError("month out of range: " + month);
    };
}
String q = quarterName(8);              // "Q3"

For an unreachable branch, throw new AssertionError() is better than an assert false statement, because it always runs and the compiler knows that the branch does not return.

5. AssertionError Is Not an Exception

The AssertionError class extends Error, not Exception. A catch (Exception e) block does not catch it, so a failed assertion stops the thread as intended, unless some code catches Throwable or Error.

String outcome;
try {
    throw new AssertionError("broken invariant");
} catch (Exception e) {
    outcome = "caught as Exception";
} catch (AssertionError e) {
    outcome = "caught as AssertionError";
}
String caught = outcome;                // "caught as AssertionError"

We should not catch AssertionError to recover from it, because a failed assertion means the program state is already wrong. Test frameworks are the exception, as the next section shows.

6. Assertions in Unit Tests

Maven Surefire runs tests with -ea by default, through its enableAssertions setting, and the Gradle test task and IDE test runners do the same. Every assert statement in the production code therefore acts as an extra check while the tests run.

The assert keyword is different from JUnit methods such as assertEquals(). JUnit assertions are normal method calls that always run inside tests, whereas the keyword is a statement in production code that runs only with -ea. In JUnit 5 assertions, the test checks the result from the outside, and the keyword checks assumptions from the inside.

7. assert Keyword FAQs

Developers who try assertions for the first time ask these questions.

7.1. Why does my assert statement not fail?

Assertions are disabled by default. Start the JVM with -ea, or add -ea to the VM options of the run configuration in the IDE.

7.2. Should we enable assertions in production?

In most projects not, because they are designed as a development aid and some checks can be expensive. Some teams enable them in staging or for a short time in production to catch rare bugs, which is safe only if no assertion has side effects.

7.3. When was the assert keyword added to Java?

In Java 1.4. Code written before that could use assert as a variable name, which is why old libraries sometimes fail to compile on newer versions.

7.4. Can we force assertions to be enabled?

A class can refuse to run without them by checking in a static initializer, with boolean on = false; assert on = true; and throwing an exception when on is still false. The Oracle guide shows this pattern, and it is rarely needed.

8. Conclusion

The assert keyword checks an assumption and throws AssertionError when it fails, but only when the JVM runs with -ea. Disabled assertions are not evaluated, so they must never contain side effects.

We use assertions for internal invariants and impossible branches, and exceptions for arguments of public methods and for anything that comes from outside the program. Test runners enable assertions by default, so a few well-placed assert statements find bugs while the tests run.

9. References

Happy Learning !!

Source Code on Github

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.