💥 Exceptions & Errors · Intermediate

Assertions in Java

assert statements, disabled by default, enabled with -ea.

🧩 The mysteryThere's a Java statement that is skipped entirely — not even evaluated — unless you start the program with a special flag. What's the point of code that usually doesn't run?

A sanity check for your own logic

**assert condition : message; states something that must be true if your code is correct. If it's false, Java throws an AssertionError** (an Error), using the expression after the colon as its message. (There's no such thing as an AssertionException.)

int idx = find(key);
assert idx >= 0 : "key must exist";

Off by default

Assertions are disabled by default. They only run when the JVM starts with **-ea** (or -enableassertions): java -ea App. When disabled, the condition isn't even evaluated — the statement is skipped entirely.

🔮 Predict it

Plain java, no -ea

Run with plain java (no -ea). What prints?

int stock = -3;
assert stock >= 0 : "negative stock";
System.out.println("stock " + stock);
  1. stock -3
  2. Throws AssertionError
  3. negative stock
Show the answer

Without -ea, the assert statement is skipped, so the program carries on and prints the stock — negative and all.

⚠️ The trap

Side effects vanish

Without -ea, the whole expression — including ++count — never runs. So count stays 0 in production but becomes 1 in tests. An assert must never do real work like changing variables or removing items.

int count = 0;
assert ++count > 0;
System.out.println(count); // 0 without -ea

Checking public arguments

✗ assert
public void setPort(int port) {
    assert port > 0;
    this.port = port;
}

Assertions are usually off in production, so bad input slips through.

✓ Always checked
public void setPort(int port) {
    if (port <= 0)
        throw new IllegalArgumentException(
            "port must be > 0");
    this.port = port;
}

Argument checks on public APIs must always run.

💼 In the real world

Where asserts belong

Use asserts for internal invariants that would mean a bug in your own code: "this list is sorted now", "this branch can't be reached". Maven's test runner (Surefire) enables assertions by default, so they fire during tests and stay silent in production.

Key takeaways

  1. assert x > 0 : "x must be positive";
  2. Off by default; enable with java -ea
  3. Failure throws AssertionError (an Error)
  4. Never use assert to validate public-method arguments or to cause side effects
🤯 Did you know?

assert became a keyword in Java 1.4 (2002). JUnit had a method named assert(), which had to be renamed assertTrue() so tests would still compile.

Practice questions

Run with plain `java` (no -ea). What does this print?

int balance = -5;
assert balance >= 0 : "negative!";
System.out.println("balance " + balance);
  1. balance -5
  2. Throws AssertionError
  3. negative!
  4. Compile error
Check your answer

balance -5. Without -ea, assert statements are skipped entirely, so the program carries on and prints the balance.

With -ea, `assert age >= 0 : "bad age";` fails. What is thrown?

  1. AssertionError with the message "bad age"
  2. IllegalArgumentException
  3. AssertionException
  4. IllegalStateException
Check your answer

AssertionError with the message "bad age". A failed assert throws java.lang.AssertionError, using the expression after the colon as its message. There is no AssertionException.

Next world: Collections — lists, sets, maps and queues. Why can removing from a list inside a loop blow up, and which collection should you actually pick?