Kotlin

What Is the Kotlin Elvis Operator? Explained Simply

What Is the Kotlin Elvis Operator? Explained Simply

If you’ve written more than a few hundred lines of Kotlin, you’ve probably typed ?: already. It’s called the elvis operator, and it does one small job. When the expression on its left comes out null, you get the value on its right instead.

It belongs to the null safety system JetBrains built into the Kotlin compiler. Every type exists in a nullable and a non-nullable version, and the compiler checks the difference before the code ever runs on a JVM or an Android device.

The reason for all this caution is pretty mundane. Harness, formerly OverOps, analyzed more than 1,000 production Java applications in 2020 and found NullPointerException topped the error list in 70% of them. Kotlin’s null safety operators were built to close off that exact failure.

What Is the Kotlin Elvis Operator?

YouTube player

Short version: ?: gives you a default value when the left-hand expression turns out null. If the left side holds a real value, you just get that value back.

Without it, you’d write a full if-else block every time a variable might come back empty. Kotlin, the statically typed language built by JetBrains, does the same check in one line.

Some people call it the null coalescing operator. You’ll also run into “null-safety operator” and “elvis expression” in docs and Stack Overflow answers. Same thing.

The syntax sits between two expressions: result = expression ?: defaultValue.

When expression resolves to something real, result gets it. When it’s null, result gets defaultValue.

Groovy used this exact ?: shorthand years before Kotlin existed. Kotlin’s designers borrowed it wholesale instead of inventing a new symbol.

And the name is a typography joke. Tilt your head and the question mark above the colon looks a bit like a quiff, which is why nobody uses a more formal name in casual conversation.

Why is Kotlin becoming the new Java?

Discover Kotlin statistics: Android adoption, multiplatform growth, developer satisfaction, and the modern language evolution from JetBrains.

Explore Kotlin Data →

Kotlin’s Null Safety System and Where the Elvis Operator Fits

YouTube player

A variable typed as String can never hold null. One typed as String? can, and the compiler won’t build your code until you’ve dealt with that possibility.

That split is a deliberate reaction to a much older problem. Tony Hoare introduced the null reference into ALGOL W back in 1965, and later admitted it cost the software industry a fortune in crashes. He called it his own billion-dollar mistake.

Kotlin moved the null check out of runtime and into the compiler, so the problem gets caught long before a program reaches a user’s device running Android development workloads.

The elvis operator works next to two other operators here. The safe call operator (?.) avoids a crash by returning null. The non-null assertion operator (!!) skips the check and trusts you. Elvis is the one that actually supplies a fallback.

Some background numbers worth having in your head:

  • Google added first-class Kotlin support for Android at Google I/O in 2017 (Google, 2017)
  • By Google I/O 2019, over 50% of professional Android developers were already using Kotlin, prompting Google to declare it the preferred language (Google, 2019)
  • Harness, formerly OverOps, analyzed more than 1,000 production Java applications and found NullPointerException topped the error list in 70% of them (Harness, 2020)
  • JetBrains shipped Kotlin 2.0 at KotlinConf in May 2024, built around the new K2 compiler (JetBrains, 2024)

That Harness figure is the failure mode Kotlin’s null handling compared to Java’s approach was built to close off. Java lets a null reference slip all the way to runtime before anything complains.

How the Kotlin Elvis Operator Evaluates Null Values

YouTube player

Left side first. The right side only runs if the left comes back null.

That ordering matters more than it looks like it should.

Evaluation Order and Short-Circuiting

The left-hand expression gets evaluated once, every time the line runs. The right-hand one is skipped completely unless the left is null.

So if the right side is a function call with side effects (a database write, say), that call never fires when the left side already holds a value.

Looking to sharpen your Kotlin skills? Data classes, extension functions, null safety, and everything else you need - including let, apply, and scope functions - is on one page in the Kotlin Cheat Sheet.

I’ve seen this bite people who stuck an expensive or side-effecting call on the right without thinking about it. You end up with a bug that only shows up sometimes, and of course it’s the kind nobody can reproduce on the first try.

Return Type Inference

Kotlin types the whole elvis expression as the nearest common supertype of both operands.

If the right side is non-null, the result is non-null too, and the compiler carries that forward with a smart cast.

  • A nullable String on the left plus a non-null String default returns a non-null String
  • A nullable Int on the left plus a nullable Int default still returns a nullable Int

This is why putting an elvis operator after a nullable call often removes the need for another null check later in the same function.

Elvis Operator vs Kotlin’s If-Else Expression

Kotlin doesn’t have a C-style ternary like condition ? a : b.

If-else fills that role. It works as an expression, so it can sit on the right side of an assignment and return a value directly.

The elvis operator can only ask whether the left side is null. If-else can test any boolean condition you throw at it: comparisons, function results, whatever the situation needs.

I’d argue the narrow scope is the point. When the question really is “is this null,” elvis says it in far less code.

ConstructTestsTypical line count
Elvis operatorNull onlyOne line
If-else expressionAny boolean conditionThree or more lines

val name = user?.name ?: "Guest" fits into one statement what an if-else block needs three or four lines for. It doesn’t say anything more than that, either.

Elvis Operator and Kotlin’s Other Null Safety Operators

YouTube player

Picking between the operators comes down to what should happen when the value is missing.

OperatorIf left side is nullIf left side has a valueCrash risk
Safe call (?.)Returns nullReturns the resultNone
Elvis (?:)Returns the fallbackReturns the left sideNone
Non-null assertion (!!)Throws NullPointerExceptionReturns the valueHigh

Elvis Operator vs Safe Call Operator

On its own, a safe call returns null and passes it further down the chain. That doesn’t solve anything. It just moves the problem one step downstream.

Put an elvis operator after it and the null gets caught and replaced with something usable, so the rest of the function never touches a nullable type.

In practice you’ll usually see them together. Safe calls walk the chain of nullable properties, and one elvis at the end makes sure the final result isn’t null.

Elvis Operator vs Non-Null Assertion Operator

!! tells the compiler to trust you. That trust costs something when you’re wrong.

Its appeal is that it’s two characters long. It’s also reasonable when null really can’t happen and you’ve already proven that somewhere else in the code.

But if the assumption is wrong, you get a NullPointerException at runtime, which is the crash Kotlin’s type system was designed to prevent. And there’s no fallback value, unlike with elvis. I avoid it outside of tests.

For the full operator reference side by side, the Kotlin cheat sheet lays out safe call, elvis, and non-null assertion on one page.

Chaining and Combining Elvis Operator Expressions

Real code rarely has one nullable value sitting alone. It’s usually nested objects, each with nullable properties of their own.

Combining Safe Call and Elvis Operator

A property lookup on a nested Kotlin data class often needs a few safe calls in a row before an elvis operator closes the chain.

val city = user?.address?.city ?: "Unknown" walks past two possible null points, user and address, and only falls back to the default at the end.

One elvis is enough here even though two objects in the chain could be null. A null anywhere short-circuits the whole expression to null before the elvis check runs.

Stacking Multiple Elvis Expressions

Stacking isn’t the same as chaining. You’re trying independent fallbacks in order:

  • First choice
  • Second choice if the first is null
  • Final hard-coded default if both are null

Written out: val display = nickname ?: fullName ?: "Anonymous".

Two or three stacked fallbacks read fine. Past that, the line becomes a puzzle, and most teams pull the logic into a small function.

Using the Elvis Operator for Return and Throw Statements

YouTube player

In Kotlin, return and throw are expressions, not just statements. That’s the only reason this pattern works.

Either one can sit on the right side of an elvis operator, which turns a null check into an early exit from the function. People usually call it a guard clause, and you’ll see it all over production code.

  1. Identify the nullable parameter or value at the top of the function
  2. Decide what should happen if it’s null: exit quietly, or fail loudly
  3. Write the elvis expression with return for a quiet exit, or throw for a hard failure
  4. Remove the old if-null-then-return block the elvis line just replaced

A function that used to open with four lines checking a parameter for null now opens with one. That’s plain code refactoring, not a new feature.

For a function argument, val name = node.getName() ?: throw IllegalArgumentException("name expected") stops execution right away with a clear message. Otherwise the null keeps traveling and fails somewhere much less obvious.

Common Elvis Operator Use Cases in Kotlin Code

YouTube player

Most real-world uses turn a maybe-null value into something the rest of the function can rely on without checking again.

Use CaseTypical Line
Default function parameterval n = name ?: "friend"
Map or collection lookupval price = prices["sku-1"] ?: 0.0
Constructor defaultclass Config(val timeout: Int = input ?: 30)
Non-null function returnfun getOrDefault() = fetch() ?: DEFAULT

Collections are probably where you’ll type it most.

A lookup on a Kotlin map returns null when the key doesn’t exist, and elvis turns that missing entry into a usable number or string on the same line.

Constructors use it a lot too. A class can accept a nullable argument and fall back to a sane default inside the constructor, so every property stored on the class stays non-nullable afterward.

Then there are function boundaries. If a function calls something nullable internally but promises a non-null return type, it almost always ends with one elvis fallback. The caller never has to check the result.

Elvis Operator Compared to Similar Operators in Other Languages

YouTube player

Plenty of mainstream languages have a version of this. Groovy’s own operator reference confirms its version came several years before Kotlin’s.

LanguageOperatorChecks forExample
Kotlin?:Null onlyname ?: "Guest"
Groovy?:Null or falsyname ?: "Guest"
C#?? / ??=Null onlyname ?? "Guest"
Swift??Nil (Optional.none)name ?? "Guest"
PHP??Null or unset$name ?? "Guest"

The symbols look nearly identical. What happens underneath is not.

Groovy checks truthiness, not only null. According to Groovy’s own language documentation, an empty string or a zero counts as false there, so the fallback can fire even when the left side technically has a value.

Kotlin narrowed this on purpose. Its elvis operator triggers on null and nothing else, which removes a whole category of surprise fallbacks that Groovy developers learn to watch for the hard way.

Swift’s nil-coalescing operator is the closest match to Kotlin. Apple’s Swift documentation defines it as shorthand for a force-unwrap inside a ternary check: unwrap the optional, or return the default.

C# has something Kotlin’s version doesn’t. Per Microsoft’s C# language reference, the compound assignment form ??= writes the fallback straight into the variable instead of just returning it.

PHP’s ?? goes a bit further than a null check. Its RFC documentation notes the operator also swallows the warning an undefined array key would normally throw, which puts it closer in spirit to Kotlin’s safe call than to a bare null test.

Java has no dedicated operator for this. The nearest built-in tool is java.util.Optional, introduced in Java 8, whose orElse() method returns a fallback value in the same spirit, just without any special syntax.

When the Elvis Operator Does Not Apply

It’s not a universal null-safety fix, and treating it like one creates its own bugs.

If the left-hand expression is already a non-null type, the compiler flags the elvis check as redundant. It adds nothing.

The right side runs again on every call

Inside a custom getter or a function that gets called many times, the right-hand side is evaluated fresh each time the left side is still null. Not once.

So a fallback built from Random.nextInt() or a logging call gives a different result on each hit. That catches developers who expected one cached value.

Empty isn’t null

An empty string, an empty list, a blank field. All of these pass straight through an elvis check, since none of them equal null.

To catch those you need isNullOrEmpty() or a similar explicit check on top of the operator.

Same with booleans and numbers. Unlike some of the languages above, Kotlin never treats false, zero, or an empty collection as a reason to use the fallback. A flag set to false passes through unchanged. That’s a deliberate design choice, and worth knowing before you assume the operator works as a general-purpose default switch.

Common Mistakes When Using the Elvis Operator

The mistake I see most is using it to hide the real bug. Wrapping every nullable value in a quick ?: "" or ?: 0 hides where the null came from instead of fixing the function that produced it.

  • The fallback silences a crash but not the underlying data problem
  • Downstream code now works with a placeholder nobody flagged as one
  • The original bug resurfaces later, somewhere harder to trace back

Some developers also reach for a lambda function with let{} when a plain elvis expression does the same job. If all you want is a default value, ?: alone reads cleaner than ?.let { it } ?: default.

Closing the chain too early

In a long chain, it’s easy to put the null check one step before the chain finishes walking through every nullable property.

Figure out which property can actually be null and put the elvis operator right after that one. Don’t just tack it onto the end out of habit.

Types drifting toward Any

A String? on the left with an Int default on the right still compiles. Kotlin quietly resolves both to their common supertype.

You end up with an Any nobody asked for. It usually shows up several lines later as a casting error, not at the line where the mistake happened, which makes it annoying to track down.

FAQ on What Is The Kotlin Elvis Operator

How many null safety operators does Kotlin have?

Besides elvis (?:), which supplies a fallback value, there’s the safe call operator (?.) that returns null instead of crashing, and the non-null assertion operator (!!) that throws if the value turns out null. That makes three null safety operators total.

Is the elvis operator unique to Kotlin?

No. Groovy had this exact ?: syntax years before Kotlin existed. C#, Swift, and PHP ship near-identical null-coalescing operators today, although each one checks slightly different conditions before falling back to a default value.

Can the elvis operator be used with function calls on the right side?

Any expression works there, function calls included. Just remember the call fires only when the left side is null. That matters for anything with side effects, like logging or network requests.

Does the elvis operator work with collections like lists and maps?

Yes. A lookup that returns null, such as a missing map key or an out-of-range index handled with getOrNull(), pairs naturally with the elvis operator. You get a default instead of passing null further along.

What Should You Check Next After What Is The Kotlin Elvis Operator?

Look at your data model. If a lot of nullable properties each need a fallback, some of them probably shouldn’t be nullable in the first place.

Turning a list into a map is usually the practical first move, since collection lookups are where most elvis fallbacks end up in production code.

After that, I’d go through things in roughly this order. Design problems get caught before syntax problems, so there’s less rework than fixing operators line by line.

  • Nullable properties that really need to stay nullable
  • Multi-property null chains collapsed into one boundary fallback
  • Collection lookups returning a real default, not a placeholder

This order holds against Kotlin’s current stable compiler behavior, checked against the language’s own documentation as of September 2026.

If a future release changes return type inference, that’s the update worth rechecking first.

Bogdan Sandu

Stay sharp. Ship better code.

Every week: one curated article, one tool worth knowing, one tip you can use tomorrow. No noise, no padding.