In Kotlin, the !!
operator is called the not-null assertion operator. It is used to tell the compiler that a null value will never be encountered for a given variable. If Kotlin encounters a null
during runtime while using !!
, it will throw a NullPointerException (NPE).
While using !!
can be convenient in some cases, it is generally discouraged because:
- It defeats Kotlin’s strong null-safety system.
- It can lead to unexpected crashes if null values occur.
Example of !!
usage:
val name: String? = getNullableName() // Can be null
val length = name!!.length // Throws NullPointerException if `name` is null.
If name
happens to be null
, the code will throw a KotlinNullPointerException
.
Strategies to Avoid NullPointerException Without !!
Instead of using !!
, you should take advantage of Kotlin’s powerful null-safety features:
1. Safe Call Operator (?.
)
The ?.
operator allows you to safely access properties or call methods on nullable objects. If the object is null, the operation is skipped, and null
is returned.
val name: String? = getNullableName()
val length = name?.length // If `name` is null, `length` will also be null
2. Elvis Operator (?:
)
The Elvis operator allows you to provide a default value if a nullable object is null.
val name: String? = getNullableName()
val length = name?.length ?: 0 // If `name` is null, default to `0`.
3. Null-Check with if
Statements
You can perform explicit null checks using conditional statements.
val name: String? = getNullableName()
if (name != null) {
val length = name.length
println("Length: $length")
} else {
println("Name is null")
}
4. let
Extension Function
The let
function is a great way to perform operations safely on a nullable value only if it is not null.
val name: String? = getNullableName()
name?.let {
println("Length: ${it.length}")
} ?: println("Name is null")
5. Smart Casts
Kotlin’s type system can automatically cast a nullable value to a non-nullable type after a null check.
val name: String? = getNullableName()
if (name != null) {
println("Length: ${name.length}") // Smart cast to non-nullable `String`.
}
6. Using Default Value in Functions
You can provide default values for parameters in functions to ensure they’re never null.
fun greet(name: String = "Guest") {
println("Hello, $name!")
}
greet(null) // Compiler error
greet() // Uses default value: "Hello, Guest!"
7. Require Non-Null Parameters
If a parameter cannot be null, declare it as a non-nullable type (String
instead of String?
). This way, Kotlin ensures null values are not passed to such parameters.
When to Use !!
Use !!
only when you’re absolutely certain that the value is never null, and a null value would indicate a programmer error or an exceptional situation.
For example:
val bundle: Bundle = intent.extras!!
val value = bundle.getString("key")!!
In this case, you’re assuming that intent.extras
and the value for the key "key"
will always exist. However, it’s better to avoid such assumptions and handle null-safety appropriately.
Summary
- Avoid
!!
as much as possible. - Use Kotlin’s built-in null-safety features like
?.
,?:
,if
,let
, and smart casts. - Reserve
!!
for situations where you’re certain about non-nullability (or avoid it altogether). Writing safer and more reliable code is one of Kotlin’s strong suits