Question
In Kotlin, what is the correct way to check whether a value is null?
For example, should I write:
if (a === null) {
// do something
}
or:
if (a == null) {
// do something
}
And for checking that a value is not null, should I use:
if (a !== null) {
// do something
}
or:
if (a != null) {
// do something
}
I want to understand which form is preferred in Kotlin and why.
Short Answer
By the end of this page, you will understand how Kotlin handles null checks, the difference between == and ===, and why a == null and a != null are the usual choices. You will also learn when referential equality with === matters and how null checks fit into everyday Kotlin code.
Concept
In Kotlin, null checking is closely tied to equality operators.
Kotlin has two main kinds of equality:
==→ structural equality===→ referential equality
Structural equality: ==
== checks whether two values are considered equal. In Kotlin, this is translated safely and works well with null.
For example:
a == null
means: "Is a equal to null?"
This is the standard and preferred way to check for null in Kotlin.
Likewise:
a != null
is the standard way to check that a value is not null.
Referential equality: ===
=== checks whether two references point to the exact same object in memory.
For most null checks, you do not use === or !==. Even though a === null works, it is not the idiomatic style for general null checking.
Why == null is preferred
Kotlin is designed so that == handles equality safely, including null. This makes code:
- easier to read
- consistent with Kotlin style
- idiomatic in most codebases
Recommended forms
Use these in normal Kotlin code:
if (a == null) {
// a is null
}
if (a != null) {
// a is not null
}
These are clear, conventional, and what most Kotlin developers expect to see.
Mental Model
Think of Kotlin equality like comparing people in two different ways.
==asks: Do these two look the same or represent the same value?===asks: Are these literally the exact same person standing here?
Now think about null as "nobody is there."
If you want to check whether a spot is empty, you usually just ask:
a == null→ "Is nobody there?"
You do not need the stricter identity-style question for normal null checks.
So:
== null= the normal empty-check!= null= the normal not-empty-check==== special identity comparison, used for object reference questions, not everyday null checks
Syntax and Examples
The usual Kotlin syntax for null checking is:
if (value == null) {
// handle null
}
if (value != null) {
// safe to use value in this block
}
Example 1: Basic null check
fun printName(name: String?) {
if (name == null) {
println("No name provided")
} else {
println("Name: $name")
}
}
Here, name is nullable because its type is String?.
- If
nameisnull, the first branch runs. - Otherwise, Kotlin knows
nameis not null inside theelseblock.
Example 2: Not-null check
fun greet(name: String?) {
if (name != null) {
println("Hello, $name")
}
}
Inside the if block, Kotlin smart-casts name to a non-null String.
Example 3: === exists, but is not the usual choice
fun check(value: String?) {
if (value === null) {
println("Value is null")
}
}
This works, but most Kotlin code uses value == null instead because it is the idiomatic form for null checking.
Key takeaway
For null checks, prefer:
value == null
value != null
Step by Step Execution
Consider this example:
fun showLength(text: String?) {
if (text != null) {
println(text.length)
} else {
println("Text is null")
}
}
Now call it like this:
showLength("Kotlin")
showLength(null)
First call: showLength("Kotlin")
textreceives the value"Kotlin".- Kotlin evaluates
text != null. - Since
textis not null, the condition istrue. - The first block runs.
- Kotlin smart-casts
textfromString?toStringinside that block. text.lengthis printed, which is6.
Second call: showLength(null)
textreceivesnull.- Kotlin evaluates
text != null. - Since
textis null, the condition isfalse. - The
elseblock runs. Text is nullis printed.
What this shows
A normal null check with != null does two useful things:
- it tests whether the value exists
- it lets Kotlin safely treat the value as non-null inside the matching block
Real World Use Cases
Null checks are everywhere in Kotlin applications because many values may be optional or missing.
API responses
A server may return optional fields:
data class User(val nickname: String?)
fun printNickname(user: User) {
if (user.nickname != null) {
println(user.nickname)
} else {
println("No nickname")
}
}
Form input validation
A field may be blank or absent:
fun validateEmail(email: String?) {
if (email == null) {
println("Email is required")
}
}
Database values
Columns can contain null:
fun processMiddleName(middleName: String?) {
if (middleName != null) {
println(middleName.uppercase())
}
}
Android or backend configuration
Configuration entries may be optional:
fun loadPort(port: Int?) {
if (port == null) {
println("Using default port")
}
}
In all of these cases, == null and != null are the normal tools.
Real Codebase Usage
In real Kotlin projects, null checks are often combined with Kotlin features that reduce boilerplate.
Guard clauses
Developers often return early when a required value is missing:
fun sendEmail(address: String?) {
if (address == null) return
println("Sending email to $address")
}
Validation before processing
fun saveUsername(username: String?) {
if (username == null) {
throw IllegalArgumentException("Username cannot be null")
}
println("Saving $username")
}
Smart casts after != null
fun printUppercase(value: String?) {
if (value != null) {
println(value.uppercase())
}
}
Prefer Kotlin null-safety tools when possible
Often, developers avoid explicit null checks by using:
- safe call:
?. - Elvis operator:
?: let
Example:
fun printLength(text: String?) {
println(text?.length ?: 0)
}
Team style and readability
Even though === null can work, most Kotlin codebases prefer == null because:
- it matches common Kotlin style
- it is easier for readers to scan
- it communicates intent clearly: this is a null check, not an identity comparison
Common Mistakes
Mistake 1: Using === for everyday null checks
if (a === null) {
// works, but not idiomatic
}
This is valid, but it suggests referential comparison when a normal null check is all you need.
Prefer:
if (a == null) {
// idiomatic Kotlin
}
Mistake 2: Confusing == and ===
Beginners often think:
==is "double equals"===is "extra strict equals"
But in Kotlin, the difference is not about being stricter in general. It is about value equality vs reference identity.
val a = "hi"
val b = "hi"
println(a == b) // true: same value
println(a === b) // may be true or false depending on reference identity
Mistake 3: Forcing non-null with !!
Broken approach:
fun printLength(text: String?) {
println(text!!.length)
}
If text is null, this throws an exception.
Safer approach:
fun printLength(text: String?) {
if (text != null) {
println(text.length)
}
}
Mistake 4: Forgetting that nullable types need handling
Broken code:
fun greet(name: String?) {
println(name.length)
}
This does not compile because name may be null.
Correct version:
fun greet(name: String?) {
if (name != null) {
println(name.length)
}
}
Mistake 5: Writing extra-complex null checks
Unnecessarily complex:
if (!(a === null)) {
println(a)
}
Clearer:
if (a != null) {
println(a)
}
Comparisons
| Operator | Meaning | Typical use | Recommended for null check? |
|---|---|---|---|
== | Structural equality | Compare values | Yes |
!= | Structural inequality | Check values are different | Yes |
=== | Referential equality | Check same object/reference | Usually no |
!== | Referential inequality | Check different references | Usually no |
== null vs === null
| Expression | Works? | Idiomatic? | Notes |
|---|---|---|---|
a == null | Yes | Yes | Preferred for normal null checks |
a === null | Yes | Usually no | Uses referential equality style |
a != null | Yes | Yes | Preferred for not-null checks |
a !== null | Yes | Usually no | Rarely needed for null checks |
== vs === with objects
data class User(val name: String)
val u1 = User("Ana")
val u2 = User("Ana")
val u3 = u1
println(u1 == u2) // true: same content
println(u1 === u2) // false: different objects
println(u1 === u3) // true: same object
This is why === is about identity, not everyday equality.
Cheat Sheet
Preferred null checks
value == null
value != null
Equality operators in Kotlin
== // structural equality
!= // structural inequality
=== // referential equality
!== // referential inequality
Rules of thumb
- Use
== nullto check for null - Use
!= nullto check for not null - Use
===only when you truly care about object identity - After
if (value != null), Kotlin can often smart-castvalue
Example
fun example(text: String?) {
if (text != null) {
println(text.length)
}
}
Related null-safety tools
text?.length // safe call
text ?: "default" // Elvis operator
text!!.length // unsafe, may throw
Best practice
For normal Kotlin code, prefer:
if (a == null) { ... }
if (a != null) { ... }
FAQ
Should I use == null or === null in Kotlin?
Use == null in normal Kotlin code. It is the idiomatic and preferred way to check for null.
Is a === null wrong in Kotlin?
No, it is not wrong. It works, but it is not the usual style for null checks.
What is the difference between == and === in Kotlin?
== checks value equality. === checks whether two references point to the exact same object.
Should I use != null or !== null?
Use != null for standard not-null checks.
Why does Kotlin allow both forms for null?
Because null can still be compared using either equality model, but Kotlin style strongly favors == and != for normal null checking.
Does if (value != null) make the value non-null inside the block?
Yes, in many cases Kotlin smart-casts the value so you can use it as non-null inside that block.
When should I use === in Kotlin?
Use it when you need to know whether two references are literally the same object, not just equal in value.
Mini Project
Description
Build a small Kotlin utility that prints information about an optional username. This project helps you practice idiomatic null checking with == null and != null, and shows how Kotlin smart casts work in real code.
Goal
Create a function that safely handles a nullable username and prints different messages depending on whether the value exists.
Requirements
- Create a function that accepts a nullable
String. - Print a fallback message when the value is
null. - Print the username and its length when the value is not
null. - Use
== nullor!= nullfor the checks. - Call the function with both a real string and
null.
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.
Add a Maven Repository URL in Gradle Kotlin DSL (build.gradle.kts)
Learn how to add Maven Central and a custom Maven repository URL in Gradle Kotlin DSL using build.gradle.kts syntax.
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.