Elvis Operator in Kotlin: ?: Doesn't Work Like You Thought

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Elvis Operator in Kotlin: Not Just "if null, then…"

\n\n

If you've ever written in Kotlin and dealt with null, you've probably seen this funny smiley with a hairstyle — the ?: operator. It's called the Elvis Operator, and in the Kotlin community it has become a real meme. But behind this simple syntax lies a surprisingly complex and interesting mechanism.

\n\n

Today we'll break down the Elvis Operator in Kotlin not as just another "syntactic sugar," but as a powerful tool that solves the null safety problem at the bytecode level. You'll learn what happens when the compiler encounters ?:, and why in some cases it works faster than if-else.

\n\n

This article is based on a real Stack Overflow question with thousands of views — we've adapted it for deep educational content. Let's go!

\n\n

What is the Elvis Operator and What's It For

\n\n

Formally, the Elvis Operator is a binary operator that returns the left operand if it is not null, and the right operand otherwise. Syntax:

\n\n
val result = nullableValue ?: defaultValue
\n\n

The name comes from its resemblance to Elvis Presley's hairstyle when you tilt your head sideways: ?: looks like eyes and a quiff. Funny enough, this name has stuck in the programming world.

\n\n

In Kotlin, this operator is part of the null safety system. It allows you to write concise code without bulky checks:

\n\n
// Instead of this:\nval length: Int\nif (str != null) {\n    length = str.length\n} else {\n    length = 0\n}\n\n// We write this:\nval length = str?.length ?: 0
\n\n

The Catch Tutorials Don't Mention

\n\n

Many people think that ?: is just a shorthand for if-else. But that's not entirely true. The Kotlin compiler generates different bytecode for these two constructs. And the difference can affect performance and program behavior.

\n\n

How ?: Works Under the Hood: Bytecode and JVM

\n\n

Let's look under the hood. Let's take a simple example and see what the Kotlin compiler turns it into for the JVM.

\n\n

Original Kotlin Code

\n\n
fun getLength(str: String?): Int {\n    return str?.length ?: 0\n}
\n\n

Decompiled Java Code (approximately)

\n\n
public static final int getLength(@Nullable String str) {\n    Integer var10000 = str != null ? str.length() : null;\n    return var10000 != null ? var10000 : 0;\n}
\n\n

See? The compiler doesn't just replace ?: with if-else. It creates a temporary variable of type Integer? (boxing!), and then applies a second ?:. This is called a double check.

\n\n

Why Does This Happen?

\n\n

Because str?.length returns Int? (nullable Int). And ?: expects that the left operand can be null. The compiler cannot "merge" these two checks into one — it must preserve the semantics of the safe call.

\n\n

As a result, if str is not null, two null checks are performed instead of one. For most applications this is unnoticeable, but in high-load loops it can become a bottleneck.

\n\n

Optimization: When the Elvis Operator is Faster Than if-else

\n\n

But there's good news too. In some cases, the Elvis Operator generates more efficient bytecode than a manual check.

\n\n

Consider an example with early return:

\n\n
// With if-else\nfun process(value: String?): String {\n    if (value == null) return "default"\n    return value.uppercase()\n}\n\n// With Elvis\nfun process(value: String?): String {                

Blogs

Book Recommendations