Kotlin Null Safety — Nullable Types and Safe Operators
Kotlin's type system distinguishes nullable from non-nullable types at compile time, eliminating most NullPointerExceptions.
What You Will Learn
- Nullable types with ?
- Safe call operator ?.
- Elvis operator ?:
- Not-null assertion !!
- Smart casts after null checks
Nullable vs Non-Nullable Types
Nullable Types
fun main() {
val name: String = "Kotlin" // cannot be null
var nick: String? = null // can be null
println(name.length) // always safe
// println(nick.length) // compile error!
println(nick?.length) // safe: prints null
nick = "Guide"
println(nick?.length) // prints 5
}String cannot be null — the compiler guarantees it. String? can be null. Calling .length on String? directly is a compile-time error. Use ?. instead.
Safe Call Operator ?.
Safe Call
fun main() {
val city: String? = null
println(city?.uppercase()) // null
println(city?.length) // null
val name: String? = "kotlin"
println(name?.uppercase()) // KOTLIN
println(name?.reversed()) // niltok
}When city is null, ?. short-circuits and returns null without calling uppercase(). When name is "kotlin", ?. calls the method normally.
Elvis Operator ?:
Elvis Operator
fun main() {
val input: String? = null
val length = input?.length ?: 0
println(length)
val name: String? = "Kotlin"
val display = name ?: "Anonymous"
println(display)
val city: String? = null
val city2 = city ?: "Unknown"
println(city2)
}input?.length is null (input is null), so ?: returns 0. name is "Kotlin" (not null), so ?: returns "Kotlin". city is null, so ?: returns "Unknown".
Not-Null Assertion !!
!! Operator
fun main() {
val value: String? = "Hello"
println(value!!.length) // safe here — value is not null
val risky: String? = null
// println(risky!!.length) // throws NullPointerException!
}value!! asserts that value is not null. Since it is "Hello", .length works fine. If value were null, it would throw KotlinNullPointerException at runtime.
Smart Casts
Smart Cast
fun greet(name: String?) {
if (name != null) {
// name is smart-cast to String (non-nullable) here
println("Hello, ${name.uppercase()}!")
} else {
println("Hello, Guest!")
}
}
fun main() {
greet("Juned")
greet(null)
}Inside the if (name != null) block, the compiler knows name cannot be null, so it is treated as String. No ?. needed inside the block.
Practice Exercise
What prints? val x: String? = null val y: String? = "Kotlin" println(x?.length ?: -1) println(y?.length ?: -1)
Quick Quiz
What does the safe call operator ?. return when the receiver is null?
Frequently Asked Questions
Related Tutorials
Written by KotlinGuide Editorial Team · Reviewed by KotlinGuide Technical Review