Kotlin handles null safety through its type system: a normal type like String cannot be null, while a nullable type like String? can be null.
1. Use nullable types when a value may be null
val name: String = "Alice" // Cannot be null
val nickname: String? = null // Can be null
If a value is nullable, Kotlin will not let you access it directly without handling the null case.
val length = nickname.length // Compile error
2. Use the safe-call operator ?.
Use ?. to access a property or call a function only when the value is not null.
val name: String? = getName()
val length: Int? = name?.length
If name is null, length becomes null instead of throwing a NullPointerException.
3. Use the Elvis operator ?: for defaults
Use ?: to provide a fallback value when something is null.
val name: String? = getName()
val length: Int = name?.length ?: 0
You can also return early or throw an exception:
fun printName(name: String?) {
val nonNullName = name ?: return
println(nonNullName)
}
fun requireName(name: String?) {
val nonNullName = name ?: error("Name is required")
println(nonNullName)
}
4. Use if null checks and smart casts
After checking that a nullable value is not null, Kotlin smart-casts it to a non-null type.
fun printLength(text: String?) {
if (text != null) {
println(text.length)
} else {
println("Text is null")
}
}
Inside the if block, text is treated as a non-null String.
5. Use let to run code only when non-null
?.let { ... } is useful when you want to execute a block only if the value exists.
val email: String? = getEmail()
email?.let {
println("Sending email to $it")
}
You can combine it with Elvis for the null case:
email?.let {
println("Sending email to $it")
} ?: println("No email available")
6. Avoid !! unless you truly mean “crash if null”
The not-null assertion operator !! converts a nullable value to a non-null value, but throws a NullPointerException if the value is null.
val name: String? = getName()
val length = name!!.length
Prefer safer alternatives:
val length = name?.length ?: 0
Use !! only when null would indicate a serious programmer error, and you want the program to fail immediately.
7. Prefer non-nullable function parameters when possible
If a function requires a value, declare it as non-nullable.
fun greet(name: String) {
println("Hello, $name")
}
If null is a valid input, declare it explicitly:
fun greet(name: String?) {
println("Hello, ${name ?: "Guest"}")
}
Quick guide
| Situation | Use |
|---|---|
| Access nullable value safely | value?.property |
| Provide default if null | value ?: default |
| Run code only if non-null | value?.let { ... } |
| Check manually | if (value != null) |
| Require non-null and crash if null | value!! |
| Disallow null entirely | Use non-null type, e.g. String |
In general: prefer non-nullable types, use ?. and ?: for safe handling, and avoid !! unless absolutely necessary.
