Question

Swift `if let` Equivalent in Kotlin: Safe Null Handling with `let`, `?.`, and `if`

Question

In Kotlin, is there an equivalent to the following Swift code?

if let a = b.val {
    
} else {
    
}

The goal is to safely unwrap a possibly null value, use it when it exists, and run alternative logic when it does not.

Short Answer

By the end of this page, you will understand how Kotlin handles nullable values and how to write the Kotlin equivalent of Swift's if let. You will learn when to use a plain if null check, when to use ?.let { ... }, and how the Elvis operator ?: helps with fallback behavior.

Concept

Kotlin does not have Swift's exact if let syntax, but it solves the same problem through its null-safety system.

In Kotlin, a variable can be either:

  • non-nullable: it must always hold a value
  • nullable: it may hold a value or null

For example:

val name: String = "Ada"      // cannot be null
val nickname: String? = null   // can be null

This matters because Kotlin prevents many null-related runtime errors at compile time. If a value might be null, Kotlin forces you to handle that case explicitly.

Swift's if let means:

  • check whether a value exists
  • if it does, unwrap it into a non-null local variable
  • otherwise, run the else branch

In Kotlin, the most direct equivalent is usually:

if (b.`val` != null) {
    val a = b.`val`
    // use a
} else {
    // handle null
}

Or more idiomatically:

b.`val`?.let { a ->
    // use a
} ?: run {
    // handle null
}

Kotlin gives you multiple ways to express this depending on what you want:

  • if (x != null) when you want a clear conditional branch
  • x?.let { ... } when you want to run code only if a value exists
  • ?: when you want a fallback value or fallback block

These patterns are used everywhere in Kotlin: Android apps, backend services, API handling, parsing, and validation.

Mental Model

Think of a nullable value like a box that may or may not contain an item.

  • Swift's if let says: "Open the box only if something is inside."
  • Kotlin says the same thing in a few different ways:
    • if (box != null): first check whether the box is empty
    • box?.let { ... }: only perform the action if the box contains something
    • box ?: fallback: if the box is empty, use something else instead

So the core idea is not the exact syntax. The real idea is: handle missing values safely before using them.

Take Quiz

Syntax and Examples

1. Direct if null check

This is the clearest equivalent to Swift if let when you want both an if and an else.

val value = b.`val`

if (value != null) {
    val a = value
    println("Value exists: $a")
} else {
    println("Value is null")
}

Here:

  • value may be null
  • if (value != null) checks for that
  • inside the if block, Kotlin knows value is non-null

2. Using ?.let

b.`val`?.let { a ->
    println("Value exists: $a")
}

This runs the block only if b.val is not null.

3. Using ?.let with an else-style fallback

b.`val`?.let { a ->
    println("Value exists: $a")
} ?: run {
    println("Value is null")
}

This is often the closest expression-style version of Swift if let ... else.

4. Using Elvis for a fallback value

If you want a replacement value instead of a branch:

val a = b.`val` ?: "default"
println(a)

If b.val is null, a becomes "default".

Note about val

In your example, the property is named val. In Kotlin, val is a keyword, so if a Java field or unusual property has that name, you may need backticks:

b.`val`

In normal Kotlin code, avoid naming properties val.

Step by Step Execution

Consider this Kotlin example:

val input: String? = "hello"

input?.let { value ->
    println("Inside let: $value")
} ?: run {
    println("Input was null")
}

Step-by-step

  1. input is declared as String?, so it may be null.
  2. input?.let { ... } means:
    • if input is not null, call let
    • if input is null, skip the block
  3. In this case, input is "hello", so the let block runs.
  4. Inside the block, value is non-null and equals "hello".
  5. The line println("Inside let: $value") prints:
Inside let: hello
  1. Because the left side was not null, the ?: run { ... } part is not used.

Now change the input:

val input: String? = null

input?.let { value ->
    println("Inside let: $value")
} ?: run {
    println("Input was null")
}

What happens now

  1. input is null.
  2. input?.let { ... } does nothing.
  3. Since the left side produced null, Kotlin evaluates the Elvis operator ?:.
  4. The run { ... } block executes.
  5. Output becomes:
Input was null

This is how Kotlin safely separates the non-null and null paths.

Real World Use Cases

API responses

A server may return an optional field:

val email: String? = response.email
email?.let {
    sendEmail(it)
} ?: run {
    log("No email address available")
}

Android UI updates

A screen may only show some data if it exists:

user.bio?.let {
    bioTextView.text = it
} ?: run {
    bioTextView.text = "No bio provided"
}

Parsing input

User input may be missing or invalid:

val ageText: String? = readLine()
if (ageText != null) {
    println("You entered: $ageText")
} else {
    println("No input provided")
}

Configuration values

Apps often use defaults when a setting is absent:

val host = config.host ?: "localhost"

Database fields

Nullable database columns are common:

record.middleName?.let {
    println("Middle name: $it")
}
Take Quiz

Real Codebase Usage

In real Kotlin projects, developers choose different null-handling styles depending on intent.

1. Guard clauses

When a value is required, developers often return early:

fun process(user: User?) {
    val validUser = user ?: return
    println(validUser.name)
}

This avoids deep nesting.

2. Validation before work

fun register(email: String?) {
    if (email == null) {
        println("Email is required")
        return
    }

    println("Registering $email")
}

3. Run code only when data exists

sessionToken?.let {
    apiClient.authenticate(it)
}

This pattern is very common for optional values.

4. Default values with Elvis

val pageSize = request.pageSize ?: 20

5. Error handling with ?: throw

val id = request.id ?: throw IllegalArgumentException("Missing id")

This is a concise and common Kotlin pattern.

6. Avoiding repeated property access

If accessing a nullable property multiple times, developers often store it first:

val currentValue = b.`val`
if (currentValue != null) {
    println(currentValue)
}

This can improve readability and avoid repeated lookups.

Common Mistakes

1. Trying to use a nullable value directly

Broken code:

val name: String? = null
println(name.length)

Problem:

  • name may be null, so Kotlin does not allow direct access to length

Fix:

println(name?.length)

or

if (name != null) {
    println(name.length)
}

2. Using let when a simple if is clearer

This works, but can be harder to read:

value?.let {
    println(it)
} ?: run {
    println("null")
}

Sometimes this is clearer:

if (value != null) {
    println(value)
} else {
    println("null")
}

Choose readability over cleverness.

3. Overusing !!

Broken idea:

println(value!!)

Problem:

  • !! crashes with a NullPointerException if the value is null

Use it only when you are absolutely sure the value cannot be null.

Safer alternatives:

value?.let { println(it) }

or

val safeValue = value ?: "fallback"

4. Forgetting that let returns a value

let is an expression. That is useful, but can also be confusing.

val result = value?.let {
    it.length
}

If value is null, then result is also null.

5. Repeating the same nullable expression many times

Less ideal:

if (b.`val` != null) {
    println(b.`val`)
}

Better:

val currentValue = b.`val`
if (currentValue != null) {
    println(currentValue)
}

This is often easier to read.

Comparisons

ApproachBest forHas else branch?Notes
if (x != null)Clear branching logicYesMost direct equivalent to Swift if let
x?.let { ... }Run code only if value existsNoConcise for non-null path only
x?.let { ... } ?: run { ... }Expression-style null/non-null branchingYesCompact but can be less readable for beginners
val y = x ?: fallbackDefault valuesNot exactlyBest when you need a replacement value
x!!Force unwrapNoRisky; can crash

Swift if let vs Kotlin patterns

SwiftKotlin equivalentUse case
if let a = value { ... }value?.let { a -> ... }Run code if value exists
if let a = value { ... } else { ... }if (value != null) { ... } else { ... }Clear two-branch logic
if let a = value { ... } else { ... }value?.let { ... } ?: run { ... }Expression-style branching
value ?? fallbackvalue ?: fallbackDefault value

For beginners, if (value != null) is usually the easiest to read.

Take Quiz

Cheat Sheet

Quick reference

Nullable type

val name: String? = null

Check for null

if (name != null) {
    println(name)
} else {
    println("null")
}

Safe call

println(name?.length)

let

name?.let {
    println(it)
}

let with fallback

name?.let {
    println(it)
} ?: run {
    println("null")
}

Elvis operator

val displayName = name ?: "Guest"

Throw if missing

val id = inputId ?: throw IllegalArgumentException("Missing id")

Avoid unless necessary

name!!

This can crash if name is null.

Rule of thumb

  • Use if (x != null) for clear branching
  • Use x?.let { ... } for a short non-null action
  • Use x ?: default for fallback values
  • Avoid !! when possible

FAQ

Is let the same as Swift if let in Kotlin?

Not exactly, but it solves a similar problem. ?.let { ... } runs code only when the value is not null.

What is the closest direct equivalent to Swift if let ... else in Kotlin?

Usually:

if (value != null) {
    // use value
} else {
    // null case
}

Should I use if or let in Kotlin for null checks?

Use if when you want clear branching. Use let when you want a concise action only for the non-null case.

What does ?: mean in Kotlin?

It is the Elvis operator. It provides a fallback when the value on the left is null.

Why does Kotlin use String??

The ? means the type is nullable. Without it, the variable cannot hold null.

Can I force unwrap like Swift's !?

Kotlin has !!, but it is risky. If the value is null, your program crashes.

Why is b.val written as b.\val`` here?

Because val is a Kotlin keyword. If a property uses that name, backticks are needed to access it.

Take Quiz

Mini Project

Description

Build a small Kotlin program that reads an optional username and prints one message if the username exists and a different message if it is null. This demonstrates the Kotlin equivalent of Swift's if let in a practical way.

Goal

Practice handling nullable values using both if null checks and ?.let with a fallback branch.

Requirements

  1. Create a nullable String variable for a username.
  2. Print a welcome message when the username is not null.
  3. Print a guest message when the username is null.
  4. Show one solution using if and another using ?.let with ?: run.
  5. Keep the program valid Kotlin and easy to read.
Take Quiz

Keep learning

Related questions

View more