Kotlin Elvis Operator

The Elvis operator ?: provides a fallback value when a nullable expression returns null. Its name comes from its shape — ?: looks like a sideways face with slicked hair, similar to Elvis Presley's signature hairstyle.

The Problem It Solves

val username: String? = null

// Without Elvis — verbose
val display = if (username != null) username else "Guest"

// With Elvis — concise
val display = username ?: "Guest"

println(display)   // Guest

How Elvis Works


expression ?: fallback

         Is the left side null?
                  │
         ┌────────┴────────┐
        YES               NO
         │                 │
   use fallback       use left side
val name: String? = "Alice"
println(name ?: "Unknown")    // Alice  (name is not null)

val city: String? = null
println(city ?: "Unknown")    // Unknown (city is null, use fallback)

Elvis with Safe Call

Combining ?. and ?: is the most common null-handling pattern in Kotlin:

data class User(val name: String, val phone: String?)

val user: User? = User("Ravi", null)

val phone = user?.phone ?: "No phone on file"
println(phone)   // No phone on file

val name = user?.name ?: "Anonymous"
println(name)    // Ravi

Chained Elvis

val a: String? = null
val b: String? = null
val c: String? = "Found it"

val result = a ?: b ?: c ?: "Default"
println(result)   // Found it

Kotlin evaluates left to right and returns the first non-null value it finds.

Elvis with throw

The right side of Elvis can also throw an exception. This is useful for enforcing required values:

fun getUser(id: Int): String? = if (id == 1) "Alice" else null

fun main() {
    val user = getUser(2) ?: throw IllegalArgumentException("User not found")
    println(user)
}

If getUser(2) returns null, an exception is thrown immediately with a clear message.

Elvis with return

fun printUserName(user: String?) {
    val name = user ?: return   // exit the function if null
    println("Hello, $name!")
}

fun main() {
    printUserName("Bob")    // Hello, Bob!
    printUserName(null)     // (nothing printed, function returns early)
}

Providing Default Numbers

val input: String? = null
val count: Int? = null

val length = input?.length ?: 0
val total  = count ?: -1

println("Length: $length")   // Length: 0
println("Total: $total")     // Total: -1

Practical Example: Dashboard Data

data class Stats(
    val visits: Int?,
    val revenue: Double?,
    val topProduct: String?
)

fun printDashboard(stats: Stats) {
    println("=== Dashboard ===")
    println("Visits     : ${stats.visits     ?: 0}")
    println("Revenue    : ₹${stats.revenue   ?: 0.0}")
    println("Top Product: ${stats.topProduct ?: "N/A"}")
}

fun main() {
    val full  = Stats(1500, 45000.0, "Laptop")
    val empty = Stats(null, null, null)

    printDashboard(full)
    println()
    printDashboard(empty)
}

Output:

=== Dashboard ===
Visits     : 1500
Revenue    : ₹45000.0
Top Product: Laptop

=== Dashboard ===
Visits     : 0
Revenue    : ₹0.0
Top Product: N/A

Leave a Comment

Your email address will not be published. Required fields are marked *