Null references have been called the billion-dollar mistake. Kotlin tackles this head-on by making null impossible in normal types. If a value can be null, you have to say so explicitly โ and then the compiler forces you to handle it safely.
Nullable types
Add a ? after the type to mark it as nullable. Without it, null isn't allowed.
fun main() {
var name: String = "Alice"
var nickname: String? = null
name = "Bob"
nickname = "Bobby"
println(name.length)
// println(nickname.length) // Error: only safe (?.) or non-null asserted (!!.) calls allowed
}
String can never hold null. String? can hold a string or null. The compiler tracks this and won't let you call methods on a nullable type without handling the null case.
Safe call operator ?.
Use ?. to call a method or access a property only if the value is not null. It returns null otherwise โ no crash.
fun main() {
val text: String? = "Hello"
val nullText: String? = null
println(text?.length)
println(nullText?.length)
val city: String? = null
val len = city?.length ?: 0
println(len)
}
The safe call returns null if the receiver is null. The Elvis operator ?: provides a default value when the expression on the left is null.
Elvis operator ?: and not-null assertion !!
The Elvis operator gives you a fallback. The not-null assertion !! says "I know this isn't null" โ but use it carefully.
fun main() {
val input: String? = "Kotlin"
val length1 = input?.length ?: -1
println(length1)
val length2 = input!!.length
println(length2)
val danger: String? = null
// danger!!.length // Would throw NullPointerException!
}
Use ?: when you want a sensible default. Avoid !! unless you are 100% sure the value isn't null โ it's basically saying "trust me, compiler, I know what I'm doing."