Question
In Java, if I have a nullable Boolean, I can write code like this:
Boolean b = ...;
if (b != null && b) {
// Do something
} else {
// Do something else
}
In Kotlin, I tried to write the equivalent using a nullable Boolean:
val b: Boolean? = ...
if (b != null && b!!) {
// Do something
} else {
// Do something else
}
This works, but using !! feels unsafe because it forces a non-null value and seems to bypass Kotlin's null-safety features.
Is there a more idiomatic and elegant way to handle a nullable Boolean in an if expression in Kotlin?
Also, there is an important detail: this works differently for local variables versus properties with backing fields. My Boolean? is actually a property with a backing field, so I would like to understand the correct approach in that case as well.
Short Answer
By the end of this page, you will understand how Kotlin handles nullable Boolean values, why !! is usually unnecessary here, when smart casts work, why properties behave differently from local variables, and the most idiomatic ways to write conditions such as if (b == true) safely.
Concept
In Kotlin, Boolean? means a Boolean that can be:
truefalsenull
That is different from plain Boolean, which can only be true or false.
This matters because an if condition must evaluate to a non-null Boolean. Kotlin will not let you directly use a Boolean? where a Boolean is required, because null is a possible value.
A common beginner reaction is to use !!:
if (b != null && b!!) {
...
}
While this may work in some cases, !! is not the idiomatic solution. The !! operator means: “I am certain this value is not null, and if I am wrong, throw a NullPointerException.”
Mental Model
Think of Boolean? as a three-state switch instead of a normal two-state switch.
A normal Boolean is like a light switch with only two positions:
- ON (
true) - OFF (
false)
A Boolean? adds a third position:
- ON (
true) - OFF (
false) - UNKNOWN (
null)
An if statement only knows how to deal with ON or OFF. It cannot directly act on UNKNOWN.
So when you write:
if (b == true)
you are really saying:
- proceed only if the switch is definitely ON
- treat OFF and UNKNOWN the same for this condition
That is why this pattern feels natural in Kotlin.
Syntax and Examples
The most useful ways to handle a nullable Boolean are shown below.
1. Check for explicit true
val b: Boolean? = getFlag()
if (b == true) {
println("Flag is true")
} else {
println("Flag is false or null")
}
This is the most idiomatic solution when you only want the true case.
2. Check for explicit false
if (b == false) {
println("Flag is explicitly false")
}
This excludes null.
3. Handle all three states separately
when (b) {
true -> println("True")
false -> println("False")
null -> println("Null")
}
Use this when null has its own meaning.
Step by Step Execution
Consider this example:
val b: Boolean? = null
if (b == true) {
println("Do something")
} else {
println("Do something else")
}
Here is what happens step by step:
bis declared asBoolean?.- Its value is
null. - Kotlin evaluates
b == true. - Since
bisnull, the comparison result isfalse. - The
ifblock is skipped. - The
elseblock runs.
Now with b = false:
val b: Boolean? = false
Execution:
b == trueis evaluated.
Real World Use Cases
Nullable Booleans show up in many real programs.
API responses
An API might send a field that is missing or unknown:
data class UserSettings(
val emailVerified: Boolean?
)
if (settings.emailVerified == true) {
showVerifiedBadge()
}
Database values
A database column may allow nulls:
if (row.isArchived == false) {
displayRecord()
}
Feature flags
A feature flag might not be initialized yet:
if (featureFlag == true) {
enableNewCheckout()
}
Form state
A checkbox value may be unset until the user interacts:
if (form.acceptedTerms == true) {
submitForm()
}
Configuration values
Optional config may default to off when missing:
val debugMode: ? = config[]
(debugMode == ) {
println()
}
Real Codebase Usage
In real Kotlin codebases, developers usually avoid !! unless they have no better option.
Common pattern: explicit true check
if (user.isAdmin == true) {
showAdminPanel()
}
This is clear and compact.
Guard clause pattern
if (request.isAuthorized != true) return
processRequest()
This is common in service methods and controllers.
Snapshot a property into a local variable
val active = session.isActive
if (active == true) {
startTracking()
}
Developers do this when smart casting is not available for a property.
Handle three states explicitly with when
when (task.completed) {
true -> markGreen()
false -> markRed()
null -> markGray()
}
This is useful when null has business meaning.
Defaulting with the Elvis operator
Common Mistakes
1. Using !! unnecessarily
Broken or risky code:
if (b!!) {
doSomething()
}
Why it is a problem:
- crashes if
bisnull - hides the fact that null is possible
Safer version:
if (b == true) {
doSomething()
}
2. Forgetting that Boolean? is not Boolean
Broken code:
val b: Boolean? = getFlag()
if (b) {
doSomething()
}
Why it fails:
ifrequires a non-nullBooleanbmight benull
Fix:
Comparisons
| Approach | Works with Boolean? | Null-safe | Idiomatic | Notes |
|---|---|---|---|---|
if (b) | No | No | No | b may be null |
if (b!!) | Yes | No | Usually no | Can throw NullPointerException |
if (b != null && b) | Sometimes | Yes | Acceptable | Works well for local variables |
if (b == true) | Yes |
Cheat Sheet
val b: Boolean? = ...
Common safe checks:
if (b == true) { ... } // only true
if (b == false) { ... } // only false
if (b != true) { ... } // false or null
if (b != false) { ... } // true or null
Convert to non-null Boolean:
val value = b ?: false
if (value) { ... }
Handle all three states:
when (b) {
true -> ...
false -> ...
null -> ...
}
Smart cast notes:
- Local
valvariables often smart cast afterb != null - Properties may not smart cast
- Mutable properties are especially restricted
- Copy a property to a local variable if needed
Avoid when possible:
FAQ
How do I check a nullable Boolean in Kotlin?
Use:
if (b == true) { ... }
This is the most common idiomatic approach.
Is b!! safe in an if condition?
No. It will crash if b is null. Use b == true unless you have a very specific reason not to.
Why does if (b != null && b) work for local variables but not always for properties?
Kotlin can smart cast local variables more easily because they are stable. Properties may change between checks or use custom getters, so Kotlin is more cautious.
What is the best way to handle a nullable property Boolean?
Usually either:
if (property == true)
or copy it first:
val value = property
if (value != null && value) { ... }
What if null has a different meaning from ?
Mini Project
Description
Build a small Kotlin program that evaluates an optional feature flag. This demonstrates how to work with a nullable Boolean safely, how to distinguish between true, false, and null, and how to avoid using !! in everyday code.
Goal
Create a program that prints different messages depending on whether a feature flag is enabled, disabled, or unknown.
Requirements
- Define a nullable Boolean feature flag
- Print one message when the flag is
true - Print a different message when the flag is
false - Print a third message when the flag is
null - Avoid using the
!!operator
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.