Question
I am trying to understand what ?: does in Kotlin, for example in this code:
val list = mutableList ?: mutableListOf()
I also want to understand why it can be rewritten like this:
val list = if (mutableList != null) mutableList else mutableListOf()
What does the ?: operator mean here, and why are these two versions equivalent?
Short Answer
By the end of this page, you will understand Kotlin's Elvis operator (?:), how it works with nullable values, and why it is equivalent to a simple if expression that checks for null. You will also see where it is commonly used in real Kotlin code and how to avoid common mistakes.
Concept
Kotlin has built-in null safety. One of the main ideas in Kotlin is that a variable can either be:
- non-nullable: it must always contain a value
- nullable: it may contain a value or
null
The Elvis operator is written as ?:.
It means:
- use the value on the left if it is not null
- otherwise use the value on the right
So this code:
val list = mutableList ?: mutableListOf()
means:
- if
mutableListis notnull, assign it tolist - otherwise, create a new empty mutable list and assign that
This is equivalent to:
val list = if (mutableList != null) mutableList else mutableListOf()
The Elvis operator matters because handling null is extremely common in real programs. Data may be missing from:
- API responses
Mental Model
Think of the Elvis operator like a backup plan.
- First, try the value on the left.
- If that value exists, use it.
- If it is missing (
null), fall back to the value on the right.
A simple analogy:
nickname ?: "Guest"
This means:
- if the user has a nickname, use it
- otherwise, use
"Guest"
So ?: is like saying: "Use this, otherwise use that."
Syntax and Examples
The basic syntax is:
val result = nullableValue ?: fallbackValue
Example 1: Default string
val name: String? = null
val displayName = name ?: "Anonymous"
println(displayName)
Output:
Anonymous
Because name is null, Kotlin uses the value on the right side.
Example 2: Your list example
val mutableList: MutableList<String>? = null
val list = mutableList ?: mutableListOf()
println(list)
Output:
[]
If mutableList already had a value, that existing list would be used instead.
Example 3: Equivalent if expression
val mutableList: MutableList<String>? =
list = (mutableList != ) {
mutableList
} {
mutableListOf()
}
Step by Step Execution
Consider this example:
val mutableList: MutableList<String>? = null
val list = mutableList ?: mutableListOf("A", "B")
println(list)
Step by step:
-
mutableListis declared asMutableList<String>?- The
?means it may benull.
- The
-
mutableListis assignednull- So right now, it does not point to any list.
-
Kotlin evaluates this expression:
mutableList ?: mutableListOf("A", "B") -
Kotlin checks the left side:
mutableList- Is it
null? - Yes.
- Is it
-
Because the left side is
null, Kotlin evaluates and uses the right side:
Real World Use Cases
The Elvis operator is used whenever a value might be missing and you want a default.
Common use cases
1. Default values for user input
val username = inputName ?: "Guest"
If the user did not provide a name, use a safe default.
2. Safe API data handling
val title = apiResponse.title ?: "Untitled"
API fields are often nullable.
3. Optional configuration values
val port = envPort ?: 8080
If no environment value exists, use a standard port.
4. Empty collections instead of null
val items = response.items ?: emptyList()
This avoids repeated null checks later.
5. Fallback object creation
val session = currentSession ?: createNewSession()
If there is no current session, create one.
6. UI display defaults
Real Codebase Usage
In real Kotlin projects, developers often use the Elvis operator in a few common patterns.
1. Guard clauses with early return
fun printName(name: String?) {
val safeName = name ?: return
println(safeName)
}
If name is null, the function returns immediately.
2. Throwing an error when a required value is missing
val token = config.token ?: throw IllegalStateException("Token is required")
This is very common when a value must exist.
3. Combining safe call and default
val itemCount = cart?.items?.size ?: 0
This safely navigates nested nullable values.
4. Replacing null collections with empty ones
val users = response.users ?: emptyList()
This makes later code simpler because you can iterate without checking for null.
5. Validation and fallback
Common Mistakes
1. Thinking ?: is a ternary operator
In some languages, ? : is a ternary conditional operator. Kotlin does not have that style of ternary operator.
For example, Java has:
condition ? value1 : value2
But Kotlin's ?: is specifically the Elvis operator, used for null fallback.
2. Using it on non-nullable values
Broken idea:
val name: String = "Sam"
val result = name ?: "Anonymous"
This is pointless because name can never be null.
Use Elvis when the left side is nullable:
val name: String? = null
val result = name ?: "Anonymous"
3. Forgetting that the right side is the fallback
Broken understanding:
val number: ? =
result = number ?:
Comparisons
Elvis operator vs if expression
| Approach | Example | Best for |
|---|---|---|
| Elvis operator | val name = input ?: "Guest" | Simple null fallback |
if expression | val name = if (input != null) input else "Guest" | When you want the logic written explicitly |
Both are equivalent for basic null checks.
Elvis operator vs safe call
| Operator | Example | What it does |
|---|---|---|
?. | user?.name | Accesses a property only if the object is not null |
Cheat Sheet
Quick syntax
val result = nullableValue ?: fallbackValue
Meaning
- Use the left side if it is not
null - Otherwise use the right side
Equivalent form
val result = if (nullableValue != null) nullableValue else fallbackValue
Common patterns
val name = input ?: "Guest"
val length = text?.length ?: 0
val users = response.users ?: emptyList()
val token = config.token ?: throw IllegalStateException("Missing token")
val item = value ?: return
Rules to remember
?:is the Elvis operator- It is used for null fallback
- It is not the same as a ternary operator from other languages
- It only checks for
null, not empty strings or empty collections - It works especially well with
?.
FAQ
What does ?: mean in Kotlin?
It is the Elvis operator. It returns the value on the left if that value is not null; otherwise, it returns the value on the right.
Is Kotlin ?: the same as the ternary operator in Java?
No. Kotlin does not have Java's condition ? a : b ternary operator. Kotlin's ?: is specifically for handling null values.
Why is mutableList ?: mutableListOf() the same as an if check?
Because both expressions do the same null test:
- if
mutableListis not null, use it - otherwise, create a new mutable list
When should I use the Elvis operator in Kotlin?
Use it when a value might be null and you want to provide a default, return early, or throw an exception.
Can I use the Elvis operator with throw or return?
Yes. This is common in Kotlin:
user = currentUser ?:
token = config.token ?: IllegalStateException()
Mini Project
Description
Build a small Kotlin program that prepares user profile data for display. Some incoming values may be null, so you will use the Elvis operator to provide safe defaults. This demonstrates a very common real-world task: cleaning nullable data before using it in an application.
Goal
Create a Kotlin program that prints a safe, user-friendly profile summary even when some input fields are null.
Requirements
- Create nullable variables for a user's name, age, and list of hobbies.
- Use the Elvis operator to provide default values for missing data.
- Print the final safe values in a readable format.
- Use at least one example that combines
?.and?:.
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.
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.
Android AlarmManager Example: Scheduling Tasks with AlarmManager
Learn how to use Android AlarmManager to schedule tasks, set alarms, and handle broadcasts with a simple beginner example.