Question
Kotlin Double-Bang Operator (!!): Meaning, Null Safety, and Safer Alternatives
Question
I am converting Java code to Kotlin in Android Studio and I see the double-bang operator (!!) used after an instance variable. What does !! mean in Kotlin, and where is this behavior documented?
For example:
copyMap!!.addMarker(
MarkerOptions()
.position(london)
.title("Marker in London")
)
Short Answer
By the end of this page, you will understand what Kotlin's !! operator does, why it is related to Kotlin's null-safety system, and why it should usually be avoided when safer alternatives exist. You will also learn how to replace !! with patterns like safe calls, if checks, let, Elvis operators, and early returns in real Kotlin code.
Concept
Kotlin has null safety built into the language. That means Kotlin tries to prevent NullPointerException errors by distinguishing between:
- non-null types like
String - nullable types like
String?
A nullable type may contain either a real value or null. Because of that, Kotlin does not let you call methods or access properties on a nullable value unless you handle the possibility of null.
The !! operator is called the not-null assertion operator.
When you write:
copyMap!!
you are telling Kotlin:
- "I am certain this value is not null."
- "Treat it as a non-null value right now."
- "If I am wrong, crash with a
NullPointerException."
So this code:
copyMap!!.addMarker(...)
means:
- Check
copyMap - If it is not null, continue and call
addMarker(...) - If it is null, throw a
NullPointerException
That is why !! is often seen as a forced unwrap or unsafe null assertion.
Why this matters
One of Kotlin's biggest benefits over Java is reducing unexpected null-related crashes. The !! operator bypasses some of that protection. It is useful in rare cases when you truly know a value cannot be null, but in everyday code it is often a sign that the nullability design could be improved.
Documentation idea
This behavior is documented as part of Kotlin's null safety and not-null assertion operator. If you search Kotlin documentation for null safety or not-null assertion operator, you will find the official explanation.
Mental Model
Think of a nullable variable as a box that might be empty.
copyMapmeans "a box that may or may not contain a map"copyMap!!means "open the box and assume something is inside"
If the box contains the value, everything works.
If the box is empty (null), your program crashes immediately.
So !! is like saying:
"Trust me, there is definitely something here."
That can be fine when you are truly certain. But if you are guessing, it is risky.
Syntax and Examples
Core syntax
value!!
This converts a nullable value into a non-null value at runtime.
- If
valueis not null, it works - If
valueis null, it throwsNullPointerException
Example with !!
val name: String? = "Kotlin"
println(name!!.length)
This prints:
6
Because name is not null.
Example that crashes
val name: String? = null
println(name!!.length)
This throws a NullPointerException because name is null.
Your example
copyMap!!.addMarker(
MarkerOptions()
.position(london)
.title("Marker in London")
)
This means copyMap is probably declared as a nullable type, such as:
var copyMap: GoogleMap? = null
Since copyMap might be null, Kotlin normally would not allow:
copyMap.addMarker(...)
Using !! tells Kotlin to proceed anyway.
Safer alternatives
Safe call
copyMap?.addMarker(
MarkerOptions()
.position(london)
.title("Marker in London")
)
If copyMap is null, nothing happens.
if check
if (copyMap != null) {
copyMap.addMarker(
MarkerOptions()
.position(london)
.title("Marker in London")
)
}
let
copyMap?.let { map ->
map.addMarker(
MarkerOptions()
.position(london)
.title("Marker in London")
)
}
Early return
val map = copyMap ?: return
map.addMarker(
MarkerOptions()
.position(london)
.title("Marker in London")
)
This is often one of the cleanest patterns.
Step by Step Execution
Consider this code:
val city: String? = "London"
println(city!!.uppercase())
Step by step
-
cityis declared asString?- This means it can hold either a
Stringornull
- This means it can hold either a
-
city!!is evaluated- Kotlin checks the runtime value of
city
- Kotlin checks the runtime value of
-
Since
cityis actually"London", the check succeeds- Kotlin treats it as a non-null
String
- Kotlin treats it as a non-null
-
uppercase()is called- Result:
LONDON
- Result:
Now compare with this:
val city: String? = null
println(city!!.uppercase())
What happens here
cityis nullable and currentlynullcity!!is evaluated- Kotlin checks the runtime value
- The value is null
- A
NullPointerExceptionis thrown immediately uppercase()is never called
Android-style example
val map = copyMap
map!!.addMarker(MarkerOptions().position(london).title("Marker in London"))
Execution flow:
- Read the value of
copyMap - Apply
!! - If
mapis non-null, calladdMarker(...) - If
mapis null, crash
This is exactly why !! should be used carefully.
Real World Use Cases
!! appears in real Kotlin code, but usually in limited situations.
Common places you may see it
- Android lifecycle code where a value is initialized before use, but Kotlin cannot prove it
- Interoperability with Java APIs that do not express nullability clearly
- Framework callbacks where a developer knows a value should exist at a specific moment
- Tests and prototypes where code is kept short and failure is acceptable
Example: Android map usage
override fun onMapReady(googleMap: GoogleMap) {
copyMap = googleMap
}
fun addLondonMarker() {
copyMap?.addMarker(
MarkerOptions().position(london).title("Marker in London")
)
}
Here, the safer approach is to only use the map after it has been initialized.
Example: reading optional configuration
val apiKey: String? = config["API_KEY"]
val keyLength = apiKey?.length ?: 0
This avoids !! and handles missing values safely.
Example: failing fast when null is a bug
val user = currentUser ?: error("Current user must be loaded before this screen opens")
This is often better than currentUser!! because the failure message is clearer.
Real Codebase Usage
In real projects, experienced Kotlin developers try to design code so !! is rare.
Common patterns used instead
Guard clauses
val map = copyMap ?: return
map.addMarker(MarkerOptions().position(london).title("Marker in London"))
This exits early if the value is missing.
Validation before work
fun showUserProfile(user: User?) {
requireNotNull(user) { "user cannot be null" }
println(user.name)
}
This is similar to !!, but gives a better error message.
Safe-call chains
val streetName = user?.address?.street?.name
This is very common in nested data structures.
Using non-null types where possible
class MapController(private val map: GoogleMap) {
fun addLondonMarker() {
map.addMarker(MarkerOptions().position(london).title("Marker in London"))
}
}
This is better design than storing a nullable map if the object should never exist without one.
lateinit for properties initialized later
lateinit var map: GoogleMap
This can sometimes replace nullable properties in Android code, but it has its own rules and should only be used when delayed initialization is guaranteed.
Practical advice
If you see many !! operators in a codebase, that often suggests:
- weak nullability design
- too many nullable properties
- missing validation at boundaries
- Java interop code that has not been cleaned up yet
Common Mistakes
1. Using !! just to silence compiler errors
Beginners often write !! because the compiler complains about nullability.
Broken approach
val name: String? = getName()
println(name!!.length)
This compiles, but may crash.
Better approach
val name: String? = getName()
println(name?.length ?: 0)
2. Assuming !! makes a value permanently non-null
!! only applies at that specific expression.
val text: String? = "Hi"
println(text!!.length)
// text is still declared as String?
The variable's type does not permanently change.
3. Using !! repeatedly
Hard-to-read code
user!!.address!!.street!!.name
This is fragile and likely to crash.
Better
val streetName = user?.address?.street?.name
Or validate once at the boundary.
4. Confusing !! with ?
?.means "only continue if not null"!!means "assume not null or crash"
Example
name?.length // safe
name!!.length // unsafe if null
5. Using !! in Android before initialization happens
Risky
var map: GoogleMap? = null
fun addMarkerNow() {
map!!.addMarker(...)
}
If onMapReady has not run yet, this crashes.
Better
fun addMarkerNow() {
val currentMap = map ?: return
currentMap.addMarker(...)
}
6. Not providing useful error messages
If null really means a bug, prefer explicit failure.
val user = currentUser ?: error("Current user should be initialized before checkout")
This is easier to debug than a plain NullPointerException.
Comparisons
| Approach | Syntax | If value is null | Best use case |
|---|---|---|---|
| Not-null assertion | value!! | Throws NullPointerException | Rare cases where null is impossible and you are certain |
| Safe call | value?.method() | Returns null or skips the call | Optional values |
| Elvis operator | value ?: fallback | Uses fallback value | Defaults and early returns |
if null check | if (value != null) | Runs only when non-null | Clear branching logic |
let with safe call | value?.let { ... } | Block is skipped | Scoped work with a non-null value |
requireNotNull | requireNotNull(value) | Throws IllegalArgumentException | Validate function inputs |
checkNotNull | checkNotNull(value) | Throws IllegalStateException | Validate object state |
!! vs ?.
user!!.name
- Crashes if
useris null
user?.name
- Safely returns
nullifuseris null
!! vs ?: return
val map = copyMap ?: return
map.addMarker(...)
This is usually cleaner than:
copyMap!!.addMarker(...)
because it makes the null case explicit and avoids a crash.
Cheat Sheet
Quick reference
What !! means
value!!
- Assert that
valueis not null - If non-null, treat it as non-null
- If null, throw
NullPointerException
Related null-safety operators
value?.method() // safe call
value ?: fallback // Elvis operator
value?.let { ... } // run block if non-null
Common replacements for !!
val map = copyMap ?: return
map.addMarker(...)
copyMap?.addMarker(...)
requireNotNull(copyMap)
copyMap.addMarker(...)
When to avoid !!
- When the value may realistically be null
- When safer handling is easy
- When writing UI or lifecycle code with delayed initialization
When it may be acceptable
- In small, controlled situations
- During migration from Java
- When null would represent a programmer error and you want immediate failure
Important rule
!! does not make your program safer. It only tells the compiler to trust you.
FAQ
What does !! mean in Kotlin?
It is the not-null assertion operator. It tells Kotlin to treat a nullable value as non-null, and it throws NullPointerException if the value is actually null.
Is !! the same as Java null checking?
No. Java often allows null access until runtime. Kotlin normally forces you to handle nulls explicitly. !! bypasses that safety and behaves more like risky Java code.
Why does Android Studio insert !! sometimes?
During Java-to-Kotlin conversion, the tool may generate !! when it cannot safely infer whether a value should be nullable or non-null.
Should I use !! in Kotlin?
Usually only rarely. Prefer safer options like ?., ?:, let, or redesigning the code to use non-null types.
What exception does !! throw?
It throws a NullPointerException if the value is null.
Is !! ever okay in production code?
Yes, but sparingly. It can be acceptable when you are certain a value cannot be null at that point and other approaches would make the code less clear.
What is better than copyMap!! in this case?
Often one of these:
copyMap?.addMarker(...)
or
val map = copyMap ?: return
map.addMarker(...)
Mini Project
Description
Build a small Kotlin example that simulates loading a map object and adding a marker only when the map is available. This demonstrates why nullable values appear in real Android-style code and how to replace !! with safer null handling.
Goal
Create a program that adds a marker only if the map has been initialized, without using !!.
Requirements
- Create a nullable map-like class reference.
- Simulate the map becoming available later.
- Add a function that tries to place a marker safely.
- Avoid using the
!!operator. - Print clear messages showing what happens before and after initialization.
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Add a Maven Repository URL in Gradle Kotlin DSL (build.gradle.kts)
Learn how to add Maven Central and a custom Maven repository URL in Gradle Kotlin DSL using build.gradle.kts syntax.
Allow HTTP and HTTPS in Android 9 Pie with Network Security Configuration
Learn how Android 9 Pie handles cleartext HTTP traffic and how to allow HTTP and HTTPS safely using network security config.