How do requireNotNull and checkNotNull work, and what do they do to the type of the value afterwards?
answer
- requireNotNull -> IllegalArgumentException; checkNotNull -> IllegalStateException
- Both RETURN the value as non-null (T from T?)
- Contract returns() implies (value != null) -> smart-cast
- Better than !! (message + right exception type)
- Lazy message, inline, no allocation
basics
~10 sThey throw if the value is null, otherwise they return the same value as a non-null type. So after calling them you can use the value without a null check.
solid answer
~30 srequireNotNull(value) throws IllegalArgumentException if value is null; checkNotNull(value) throws IllegalStateException if null. Crucially both are declared to RETURN the value as a non-null type (T from T?), so the idiom is val x = requireNotNull(nullable). They are also annotated with Kotlin contracts (returns() implies (value != null)), which lets the compiler smart-cast the original variable to non-null after the call even when you ignore the return value. Both take a lazy message lambda. Prefer them over the !! operator because they give a meaningful message and the right exception semantics (bad argument vs bad state) instead of a bare NullPointerException.
code
kotlin · 6 linesfun loadUser(id: String?, session: Session?): User {
val realId = requireNotNull(id) { "id must not be null" } // IllegalArgumentException
checkNotNull(session) { "session not initialized" } // IllegalStateException
// session smart-cast to non-null below thanks to the contract
return repository.find(realId, session.token)
}go deeper
Knows they throw on null and let you use the value without a further null check.
Distinguishes the two exception types, knows they return the non-null value, and prefers them over !! for messages.
Explains the Kotlin contract returns()-implies clause enabling smart-cast even when the return value is discarded, and stability requirements.
Discusses contracts as an API-design tool, smart-cast stability rules across mutable/delegated state, and consistent null-failure taxonomy across a codebase.
## The two functions - `requireNotNull(value)` -> throws `IllegalArgumentException` if `value` is `null` (bad argument). - `checkNotNull(value)` -> throws `IllegalStateException` if `value` is `null` (bad state). ## Two ways they remove nullability **1. Return type.** Each is generic and returns the value as a non-null type: ```kotlin public inline fun <T : Any> requireNotNull(value: T?): T ``` So you can capture the narrowed value: ```kotlin val name: String = requireNotNull(maybeName) { "name required" } ``` **2. Kotlin contract -> smart-cast.** Both functions carry a `contract { returns() implies (value != null) }`. A *contract* is a stdlib mechanism that tells the compiler what is guaranteed if the function returns normally. Here it guarantees the argument is non-null, so the compiler **smart-casts** the original variable even if you discard the return value: ```kotlin fun greet(name: String?) { requireNotNull(name) println(name.length) // name smart-cast to String, no ?. needed } ``` *Smart-cast* = the compiler automatically treats a variable as a more specific (here non-null) type after a proven check. ## Why prefer them over !! The `!!` operator also asserts non-null but throws a bare `NullPointerException` with no message and the wrong semantic flavor. `requireNotNull` / `checkNotNull` give a descriptive lazy message and the correct exception type that says **whose fault** the null is. ## Lazy message The message lambda `{ ... }` runs only when the value is actually null, so it is free on the happy path, and because the functions are `inline` no lambda object is allocated.
- If you ignore the return value of requireNotNull, can you still use the variable as non-null?Yes, for a stable variable (e.g. a local val) the contract smart-casts it to non-null after the call.
- When would smart-cast NOT apply even after requireNotNull?If the value is a mutable var that could change concurrently, or a custom getter / delegated property the compiler cannot prove is stable.
saying these in an interview costs you the question
- Saying they return Unit / do not return the value
- Claiming checkNotNull throws IllegalArgumentException
- Treating them as identical to !! with no benefits
- Not knowing about the contract-based smart-cast
- Believing the message is evaluated even when value is non-null