Question

Kotlin Double-Bang Operator (!!): Meaning, Null Safety, and Safer Alternatives

kotlinkotlin-null-safety

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:

  1. Check copyMap
  2. If it is not null, continue and call addMarker(...)
  3. 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.

  • copyMap means "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.

Take Quiz

Syntax and Examples

Core syntax

value!!

This converts a nullable value into a non-null value at runtime.

  • If value is not null, it works
  • If value is null, it throws NullPointerException

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

  1. city is declared as String?

    • This means it can hold either a String or null
  2. city!! is evaluated

    • Kotlin checks the runtime value of city
  3. Since city is actually "London", the check succeeds

    • Kotlin treats it as a non-null String
  4. uppercase() is called

    • Result: LONDON

Now compare with this:

val city: String? = null
println(city!!.uppercase())

What happens here

  1. city is nullable and currently null
  2. city!! is evaluated
  3. Kotlin checks the runtime value
  4. The value is null
  5. A NullPointerException is thrown immediately
  6. uppercase() is never called

Android-style example

val map = copyMap
map!!.addMarker(MarkerOptions().position(london).title("Marker in London"))

Execution flow:

  1. Read the value of copyMap
  2. Apply !!
  3. If map is non-null, call addMarker(...)
  4. If map is 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.

Take Quiz

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

ApproachSyntaxIf value is nullBest use case
Not-null assertionvalue!!Throws NullPointerExceptionRare cases where null is impossible and you are certain
Safe callvalue?.method()Returns null or skips the callOptional values
Elvis operatorvalue ?: fallbackUses fallback valueDefaults and early returns
if null checkif (value != null)Runs only when non-nullClear branching logic
let with safe callvalue?.let { ... }Block is skippedScoped work with a non-null value
requireNotNullrequireNotNull(value)Throws IllegalArgumentExceptionValidate function inputs
checkNotNullcheckNotNull(value)Throws IllegalStateExceptionValidate object state

!! vs ?.

user!!.name
  • Crashes if user is null
user?.name
  • Safely returns null if user is 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.

Take Quiz

Cheat Sheet

Quick reference

What !! means

value!!
  • Assert that value is 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(...)
Take Quiz

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

  1. Create a nullable map-like class reference.
  2. Simulate the map becoming available later.
  3. Add a function that tries to place a marker safely.
  4. Avoid using the !! operator.
  5. Print clear messages showing what happens before and after initialization.
Take Quiz

Keep learning

Related questions

View more