How does Kotlin's assert function differ from require/check, and when is it actually evaluated on the JVM?
answer
- assert -> AssertionError, off by default, needs -ea
- require/check/error always run; assert may not
- Never validate real input with assert
- assert is for internal invariants / debug
- No side effects inside an assert condition
basics
~20 sassert checks an internal sanity condition but can be turned off. On the JVM it only runs when assertions are enabled with the -ea flag. require and check always run. So never use assert to validate real input.
solid answer
~40 sassert(value) throws AssertionError if value is false, but only when JVM assertions are enabled (-ea / -enableassertions); by default they are disabled, so the check is effectively skipped in normal runs. It is meant for internal invariants/developer sanity checks, not for validating arguments or external state. require/check, by contrast, are always active and throw IllegalArgumentException/IllegalStateException — use them for contracts that must hold in production. A subtlety: Kotlin's assert is an inline function, so even when assertions are disabled the value expression and the optional lazy message can be more carefully gated, but you must still not rely on assert for side-effecting validation. Rule of thumb: require for inputs, check for state, error for unreachable code, assert only for optional internal debugging checks.
code
kotlin · 6 linesfun process(input: String?) {
requireNotNull(input) // production contract, always runs
val parsed = parse(input)
assert(parsed.isValid()) { "parser produced invalid result" } // dev-only sanity check
}
// Run with: java -ea ... to actually enable the assertgo deeper
Knows assert checks a condition but that require/check are the ones to rely on for real validation.
States that assert is disabled by default and throws AssertionError, unlike the always-on require/check.
Explains the -ea toggle and desiredAssertionStatus, the side-effect pitfall, and a precise table of when to use each guard.
Sets team policy on assert usage, reasons about test vs prod assertion enablement, and the risks of invariants that only hold under -ea.
## What assert is `assert(value: Boolean)` (and the overload `assert(value) { lazyMessage }`) throws `AssertionError` when `value` is `false`. It mirrors Java's `assert` keyword and is meant for **internal invariants** — "this should never happen if my code is correct." ## The crucial difference: it can be disabled On the JVM, assertions are **off by default**. They run only when the JVM is started with `-ea` (or `-enableassertions`). So in a normal production run: ```kotlin assert(cache.size <= maxSize) { "cache overflow" } ``` ...is effectively a no-op unless `-ea` is set. By contrast: - `require` / `requireNotNull` -> **always** throw `IllegalArgumentException`. - `check` / `checkNotNull` -> **always** throw `IllegalStateException`. - `error` -> **always** throws `IllegalStateException`. None of these can be turned off. That is why you must **never** use `assert` to validate untrusted input or enforce a real contract — if assertions are disabled the bad value sails through. ## How Kotlin implements the toggle Kotlin's `assert` reads the host class's assertion status (the same `desiredAssertionStatus` mechanism Java uses) and only evaluates/throws when enabled. The condition and the lazy message overload mean the message is built only on the failure path; but if assertions are disabled the whole thing is skipped. ## When to use which | Need | Use | Throws | Disable-able? | |------|-----|--------|---------------| | Validate an argument | require | IllegalArgumentException | No | | Validate object/program state | check | IllegalStateException | No | | Mark unreachable code | error | IllegalStateException (Nothing) | No | | Optional internal sanity check | assert | AssertionError | Yes (-ea) | ## Gotcha: side effects in assert Because `assert` may not run, never put **required side effects** in its condition. `assert(list.removeIf { it.isStale() })` would silently stop pruning when assertions are off.
- Why is using assert for argument validation considered a bug?Assertions are disabled by default in production, so the invalid argument would not be rejected; require must be used instead.
- How do you enable Kotlin asserts at runtime?Start the JVM with -ea (-enableassertions), optionally scoped to packages/classes; otherwise assert bodies are skipped.
assert is a smoke detector you can unplug for the demo; require/check are the building code that always applies.
saying these in an interview costs you the question
- Using assert to validate method arguments or external input
- Believing assert always runs like require/check
- Putting required side effects inside an assert condition
- Thinking assert throws IllegalStateException (it throws AssertionError)
- Not knowing about the -ea JVM flag