Definition
assert condition : "message"checks developer assumptions during development. If the condition is false, it throwsAssertionError.- Assertions are disabled by default in production. They cost zero at runtime when disabled. Enable with
-eaJVM flag. - Never use assert for public method parameter validation. In production, assertions are off, so the validation is skipped entirely.
- Use
IllegalArgumentException,Objects.requireNonNull(), or Guava'sPreconditionsfor public API validation since they are always active. - Assert is for catching developer errors (invariants, postconditions, unreachable code), not user errors.
Assert is like Rajesh's sticky note on his monitor: "balance should never be null here. If it is, my code has a bug." It is a developer tool. When the bank opens to customers (production), the sticky note is removed. You would never use a sticky note as the actual security system. For input validation, use real guards (throw IllegalArgumentException) that work 24/7.
Understanding the Concepts
What is the assert keyword?
The assert keyword checks conditions that should always be true if the code is correct. If the condition is false, it throws AssertionError.
package com.bank.demo;
import java.math.BigDecimal;
public class AssertBasicDemo {
// Private method: assert is appropriate for internal invariants
private static BigDecimal calculateInterest(BigDecimal balance, BigDecimal rate) {
assert balance != null : "Internal bug: balance is null";
assert rate.signum() >= 0 : "Internal bug: rate is negative";
return balance.multiply(rate);
}
public static void main(String[] args) {
// Run with: java -ea com.bank.demo.AssertBasicDemo
BigDecimal interest = calculateInterest(new BigDecimal("100000"), new BigDecimal("0.085"));
System.out.println("Interest: Rs." + interest);
// Without -ea: assert is completely skipped, zero cost
System.out.println("Assertions enabled: " +
AssertBasicDemo.class.desiredAssertionStatus());
}
}
Interest: Rs.8500.000
Assertions enabled: false
Why should you never use assert for public API validation?
In production, assertions are disabled. If you validate with assert, the check is skipped and invalid input flows through unchecked.
package com.bank.demo;
import java.math.BigDecimal;
public class AssertVsExceptionDemo {
// WRONG: assert for public API validation
public static void wrongWithdraw(BigDecimal amount) {
assert amount != null && amount.signum() > 0 : "Amount must be positive";
// In production (-ea NOT set): assert SKIPPED!
// Negative amount accepted. Balance corrupted.
System.out.println("Wrong: withdrawn Rs." + amount);
}
// CORRECT: exception for public API validation
public static void correctWithdraw(BigDecimal amount) {
if (amount == null || amount.signum() <= 0) {
throw new IllegalArgumentException("Amount must be positive: " + amount);
}
System.out.println("Correct: withdrawn Rs." + amount);
}
public static void main(String[] args) {
// Without -ea, assert is skipped:
wrongWithdraw(new BigDecimal("-100")); // No error in production!
try {
correctWithdraw(new BigDecimal("-100")); // Always throws
} catch (IllegalArgumentException e) {
System.out.println("Caught: " + e.getMessage());
}
}
}
Wrong: withdrawn Rs.-100
Caught: Amount must be positive: -100
When is assert appropriate?
Assert is for internal invariants: conditions that should never be false if your code is correct.
package com.bank.demo;
public class AssertAppropriateUse {
// 1. Post-condition: verify method's promise
private static int[] sortArray(int[] arr) {
java.util.Arrays.sort(arr);
assert isSorted(arr) : "Bug: array not sorted after sort()";
return arr;
}
private static boolean isSorted(int[] arr) {
for (int i = 1; i < arr.length; i++) {
if (arr[i] < arr[i - 1]) return false;
}
return true;
}
// 2. Unreachable code
private static String getAccountType(int code) {
return switch (code) {
case 1 -> "SAVINGS";
case 2 -> "CURRENT";
case 3 -> "FIXED_DEPOSIT";
default -> {
assert false : "Bug: unknown account code " + code;
yield "UNKNOWN";
}
};
}
public static void main(String[] args) {
int[] sorted = sortArray(new int[]{5, 3, 1, 4, 2});
System.out.println("Sorted: " + java.util.Arrays.toString(sorted));
System.out.println("Type 1: " + getAccountType(1));
}
}
Sorted: [1, 2, 3, 4, 5]
Type 1: SAVINGS
How does assert compare to exceptions?
| Feature | assert | IllegalArgumentException |
|---|---|---|
| Purpose | Developer invariant check | Public API validation |
| Active in production | No (disabled by default) | Yes (always) |
| Throws | AssertionError (Error) | IllegalArgumentException (Exception) |
| Should catch? | No | Yes (or let propagate) |
| Performance when off | Zero cost | Always runs |
| Enable | -ea JVM flag | Always enabled |
What should a senior engineer know?
- JUnit assertions are different.
assertEquals()in JUnit is always active during tests. Java'sassertkeyword depends on the-eaflag. - Selective enabling.
java -ea:com.bank.service...enables assertions for a specific package only. - Design by Contract. Assert is Java's limited implementation of Design by Contract (DBC). Kotlin's
require()andcheck()are the modern equivalent that are always active.
What are common interview follow-up questions?
- Is assert enabled by default? (No. Use
-eato enable.) - What does assert throw? (AssertionError, which extends Error.)
- Can you catch AssertionError? (Technically yes, but you should not.)
- What replaces assert for public validation? (IllegalArgumentException, Objects.requireNonNull().)
Visual Overview
assert balance > 0 : "Bug!";
│
├── With -ea flag:
│ condition false → throw AssertionError
│ condition true → continue
│
└── Without -ea (default):
Statement completely SKIPPED
Zero cost
For public APIs, use:
if (balance <= 0)
throw new IllegalArgumentException("...");
Always active. Cannot be disabled.
Key Takeaway
The assert keyword checks developer invariants during development: conditions that should never be false if the code is correct. It throws AssertionError when the condition is false. The critical fact is that assertions are disabled by default in production. They cost zero when disabled and are only activated with the -ea JVM flag.
Never use assert for public method parameter validation. In production, the assertion is skipped entirely, and invalid input flows through unchecked. At National Bank of India, assert amount > 0 in a withdrawal method means negative amounts are accepted in production, corrupting account balances. Use if (amount <= 0) throw new IllegalArgumentException() instead, which is always active.
Assert is appropriate for three purposes: private method preconditions ("this should never be null if my caller is correct"), postconditions ("the sorted array should actually be sorted"), and unreachable code branches ("default case that should never happen").
Remember one sentence: assert is disabled in production so never use it for public API validation, and use IllegalArgumentException or Objects.requireNonNull instead.
---