Как запустить код, если объект нулевой?

В Kotlin я могу запустить код, если объект не является нулевым, как это:

data?.let {
    ... // execute this block if not null
}

но как я могу выполнить блок кода, если объект нулевой?

10 ответов

Решение

Просто используйте нормальный if:

if (data == null) {
  // Do something
}

Вы можете использовать операторelvis и оценить другой блок кода с помощью run { ... }:

data?.let {
    // execute this block if not null
} ?: run {
    // execute this block if null
}

Но это, кажется, не так легко читается, как простой if-else заявление.

Кроме того, вы могли бы найти этот Q&A полезным:

Вот краткий синтаксис с использованием оператора Элвиса. Напомним, что оператор Элвиса выполняет только правую сторону, если левая сторона оценивается как ноль.

data ?: doSomething()

Вы можете создать инфиксную функцию следующим образом:

infix fun Any?.ifNull(block: () -> Unit) { 
  if (this == null) block()
}

Тогда вы можете сделать это:

data ifNull {
  // Do something
}

Вы можете использовать ниже код

myNullable?.let {

} ?: { 
    // do something
}()

также вы можете опустить fun()

myNullable?.let {

} ?: fun() { 
    // do something
}()

или вы можете позвонить invoke() вместо ()

myNullable?.let {

} ?: fun() { 
    // do something
}.invoke()

Обратите внимание, что возвращаемое значение отличается, как показано ниже.

val res0 = myNullable?.let {
} ?: () {

}()
val res1 = myNullable?.let {
} ?: fun() {
    "result"    
}()
val res2 = myNullable?.let {
} ?: () {
    "result"    
}()


println("res0:$res0")
println("res1:$res1")
println("res2:$res2")

РЕЗУЛЬТАТ:

res0:kotlin.Unit // () {} with empty
res1:kotlin.Unit // fun() {}
res2:result      // () {} with return

let также может применяться к null, независимо от того, является ли объект нулевым или нет:

      data.let {d->
    if (d != null){
        // execute this block if data is not null
    } else {
        // for data is null
    }
}

Обычно это делается с помощью следующих языковых конструкций:

      data?.also {
    // execute this block if not null
} ?: run {
    // execute this block if null
}

будь осторожен с

      data?.let {
    // execute this block if not null
    // but careful, returning null accidenatlly will execute run {} as well.
    null
} ?: run {
    // execute this block if null
}

Блок let может случайно вернуть нулевую переменную, и блок run также будет выполнен.

Если вам не нравятся конструкцииalsoиrunвы можете изменить имя на что-то вроде ниже:

      inline fun <T> T?.ifNotNull(block: (T) -> Unit): T? {
    if (this != null) {
        block(this)
    }
    return this
}

inline fun <T> T.elseIfNull(block: () -> Unit) {
    if (this == null) { block() }
}

и используйте так:

      class A
var a1: A? = null
var a2: A? = A()
 
a1.ifNotNull {
    println("a1 is Not Null: $it")
}.elseIfNull {
    println("Is null do something else")           
}

a2.ifNotNull {
    println("a2 is Not Null $it")
}.elseIfNull {
    println("Is null do something else")           
}

Вышеуказанная гарантия, что второй блок не будет выполнен, если верхний случайно вернет ноль.

Я предпочитаю это решение,

fun runIfNull(any: Any?, block: () -> Unit) {
        if (any == null) block()
}

Что вы используете как:

runIfNull(any) { // it will run; }

Он имеет преимущество по сравнению с ответом @Dmitry Ryadnenko, где можно запутаться и использовать его неправильно.
У вас есть функция

infix fun Any?.ifNull(block: () -> Unit) { 
  if (this == null) block()
}

И в случае, если вы используете его для нулевого объекта следующим образом:

nullObject?.ifNull { // THIS WILL NOT BE CALLED }
nullObject.ifNull { // this will be called }

Блок не будет выполняться.
Обратите внимание на ошибочно добавленный вопросительный знак "?"

Следующий ответ - более простая версия этого ответа.
Функция возвращает действительный список, если цепочка вызовов успешна,
иначе
возвращается 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()) //[]
}

Еще один хороший вариант использования when:

when(myVariable){   
    null -> {
            // execute your null case here
        }
    else -> { // non null case }
}

when довольно универсален, поэтому вы можете указать точные условия, включая нулевой регистр.

Другие вопросы по тегам