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.

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.
| Switch | Effect |
|---|---|
| -ea or -enableassertions | Enables assertions in all application classes |
| -da or -disableassertions | Disables 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.Cart | Enables assertions in one class |
| -ea -da:com.shop.Cart | Enables assertions everywhere except one class |
| -esa or -enablesystemassertions | Enables 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 for | Use an exception for |
|---|---|
| Invariants inside a class, such as a balance that is never negative | Arguments of public methods, with Objects.requireNonNull() or IllegalArgumentException |
| Results of private helper methods | User input, file content and network data |
| Branches that should never run, such as an impossible default case | Missing configuration or resources |
| Loop invariants in algorithms | Any 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
- JLS 25, The assert Statement
- Oracle, Programming With Assertions
- The java Command (Java SE 25)
- AssertionError (Java SE 25 API)
Happy Learning !!