Nullable Types / ?. Operator
Kotlin guarantees null safety at the type system level. Regular types cannot hold null; to store a null value, use a Nullable type written as Type?. Operations on Nullable types use the safe call operator ?. to prevent null access errors.
Syntax
// Declaring a Nullable type var name: String? = "Alice" name = null // OK // A non-Nullable type cannot hold null. // var nonNull: String = null // Compile error // Safe call operator (?.) — skips the call and returns null if the receiver is null. val length = name?.length // Type is String? (may be null) val upper = name?.uppercase() // Returns null if name is null, otherwise uppercased // Chained safe calls val trimmed = name?.trim()?.uppercase()
Syntax Overview
| Syntax | Description |
|---|---|
| Type? | A Nullable type. Can hold null. |
| ?.method() | Safe call. Skips the method and returns null if the receiver is null. |
| ?.property | Safe property access. Returns null if the receiver is null. |
| if (x != null) | Inside the block after a null check, the variable is automatically smart-cast to a non-Nullable type. |
| ?.let { } | Executes the block only when the value is not null. |
Sample Code
fun getUser(id: Int): String? {
return if (id == 1) "Alice" else null
}
fun main() {
// Nullable type basics
var name: String? = "Alice"
println(name) // Alice
name = null
println(name) // null
// Safe call operator (?.)
val user1 = getUser(1)
val user2 = getUser(99)
println(user1?.length) // 5
println(user2?.length) // null (no NullPointerException)
// Chained safe calls
println(user1?.uppercase()?.reversed()) // ECILA
println(user2?.uppercase()?.reversed()) // null
// Smart cast after a null check
val value: String? = "Hello, Kotlin!"
if (value != null) {
// Inside this block, value is treated as String (non-Nullable).
println(value.length) // 14 (?. is not needed)
println(value.uppercase()) // HELLO, KOTLIN!
}
// Use ?.let to run code only when the value is not null.
val optional: String? = "world"
optional?.let { str ->
println("Has value: ${str.uppercase()}") // WORLD
}
val nothing: String? = null
nothing?.let { str ->
println("This will not be executed")
}
println("Skipped because the value is null")
// Filtering nulls from a list
val items: List<String?> = listOf("a", null, "b", null, "c")
val nonNull = items.filterNotNull() // Removes null values.
println(nonNull) // [a, b, c]
}
Notes
Kotlin's null safety is a compile-time mechanism that prevents NullPointerExceptions. The type system distinguishes between Nullable types (String?) and non-Nullable types (String). Any operation on a Nullable type must use either a safe call (?.) or an explicit null check.
When calling Java code from Kotlin, Java types are treated as "platform types" (their nullability is unknown). In this case, using ?. or annotating the Java side with nullability annotations is the safe approach.
For providing a default value when null, see ?: Elvis Operator. For force-unwrapping a Nullable value, see !! Non-null Assertion.
If you find any errors or copyright issues, please contact us.