In Kotlin, I can run code if an object is not null like this:
data?.let {
// execute this block if not null
}
But how can I execute a block of code if the object is null?
In Kotlin, I can run code if an object is not null like this:
data?.let {
// execute this block if not null
}
But how can I execute a block of code if the object is null?
You can use the elvis operator and evaluate another block of code with run { ... }
:
data?.let {
// execute this block if not null
} ?: run {
// execute this block if null
}
But this seems not to be quite as readable as a simple if
-else
statement.
Also, you might find this Q&A useful:
Here's a concise syntax using the Elvis operator. Recall the Elvis operator only executes the right side if the left side evaluates to null.
data ?: doSomething()
You can create an infix function like this:
infix fun Any?.ifNull(block: () -> Unit) {
if (this == null) block()
}
Then you can do this:
data ifNull {
// Do something
}
Just use a normal if
:
if (data == null) {
// Do something
}
You can use below code
myNullable?.let {
} ?: {
// do something
}()
also you can omit fun()
myNullable?.let {
} ?: fun() {
// do something
}()
or you can call invoke()
instead of ()
myNullable?.let {
} ?: fun() {
// do something
}.invoke()
Note that returning value differs like below.
val res0 = myNullable?.let {
} ?: () {
}()
val res1 = myNullable?.let {
} ?: fun() {
"result"
}()
val res2 = myNullable?.let {
} ?: () {
"result"
}()
println("res0:$res0")
println("res1:$res1")
println("res2:$res2")
RESULT:
res0:kotlin.Unit // () {} with empty
res1:kotlin.Unit // fun() {}
res2:result // () {} with return
let can apply on null as well, regardless if the object is null or not:
data.let {d->
if (d != null){
// execute this block if data is not null
} else {
// for data is null
}
}
I prefer this solution,
fun runIfNull(any: Any?, block: () -> Unit) {
if (any == null) block()
}
Which you use as:
runIfNull(any) { // it will run; }
It has an advantage comparing to @Dmitry Ryadnenko's answer,
where one might be confused and might use it incorrectly.
There you have a function
infix fun Any?.ifNull(block: () -> Unit) {
if (this == null) block()
}
And in case you use it on a null object in the way:
nullObject?.ifNull { // THIS WILL NOT BE CALLED }
nullObject.ifNull { // this will be called }
The block is not going to be executed.
Please note the mistakenly added question mark '?'
Following answer is simpler version of this answer.
Function returns valid list if chain calls are successful
else
returns emptyList()
class A(var b: B? = null)
class B(var c: C? = null)
class C(var d: D? = null)
class D(var list: List<String>?)
//1. Note ? in A?.<functionName>
fun A?.isNull(): List<String> {
if(this == null) { // 2. access object using this keyword
return emptyList<String>()
}
return this.b?.c?.d?.list ?: emptyList<String>()
}
fun main() {
//1. Empty A object
var a: A? = A()
println(a.isNull()) //[]
//2. Null A object
a = null
println(a.isNull()) //[]
//3. All Valid chaining parameters
val d = D(listOf("d"))
val c = C(d)
var b : B? = B(c)
a = A(b)
println(a.isNull()) //[d]
//4. Invalid chain parameter
b = null
a = A(b)
println(a.isNull()) //[]
}