如何避免嵌套"空检查"被"?.let"?



让kotlin在kotlin中帮助我避免(null?(dosomething。

但是我有问题。

a是对象的字段,b是对象A的字段。它们可以是nullbale。

他们在这样的代码中。

class Obj {
   var a : A?
}
class A {
   var b : B?
}

我知道我可以通过double Let:

做到这一点
A?.let { 
   it.B.let {
      // a must nonnull
   }
}
A?.B?.let {
  // how to use A ,without null check again? 
}

有扩展功能可以实现所需的目标,您可以在此线程中找到它们https://discuss.kotlinlang.org/t/kotlin-null-null-check - 用于毫无用的瓦尔瓦尔/1946

,但老实说,您可能会更好地使用基本如果在此处检查基本,则如果变量可变,则可以将其分配给val

val _a = a
val _b = b
if (_a != null && _b != null) {
}

编辑:如果您仍然真正想使用,那么,对于这种情况,您可以创建一对并使用takeIf

(a to b)
    .takeIf { (a, b) ->
        a != null && b != null
    }
    ?.let { (a, b) ->
    }

但是,编译器不会将值智能播放为非挂钩,因此您仍然必须对它们执行非挂钩(!!(断言。

您可以像 swift guard一样用猫王 ?:

来实现它
fun doSomething() {
    val a = A ?: return
    val b = B ?: return
    doSomethingWith(a, b)
}

此处的ab是您在这种情况下持有的数据的不可删除的引用。

默认情况下kotlin避免null值,对于Null Safety,它提供了:

1(安全致电操作员(?。(
2(没有无效断言(!!(
3(猫王opeartor(?:(
4(let(?let {...}(

安全呼叫
  • 安全呼叫操作员(?。(:检查属性在执行任何操作之前是否未null。

  • not-null断言(!!(:明确地告诉编译器该属性不是零,如果是零,请扔一个null指针异常(NPE(

  • elvis opeartor(?:(:就像java中的三元运算符一样。如果属性不是null,则返回左表示。

  • let(?let {...}(安全呼叫:仅当属性不为null null

  • 时,它才会执行Let Block

示例在属性中没有零值:

    fun main() {
      val name: String? = "Sumit"
      println("Safe Call operator: ${name?.length}")
      name?.let {
          println("Safe Call wih let operator: ${name.length}")
      }
      val length = name?.length ?: 0
      println("Elvis operator : $length")
      println("Not Null Assertion Operator : ${name!!.length}")
   }  

output(属性内的无零值(
安全电话操作员:5
安全致电WIH让操作员:5
猫王操作员:5
不是零断言操作员:5

output(属性中的空值((val名称:字符串?= null(

Safe Call operator: null
Elvis operator : 0
Exception in thread "main" kotlin.KotlinNullPointerException
  at HelloKt.main(Hello.kt:14)
  at HelloKt.main(Hello.kt)

在这里,安全打电话没有执行!和非杀伤断言操作员抛出无指针异常。

您的问题可以使用不播放断言操作员:

A?.B?.let {   
    // If A and B are not null then only this block will be executed.  
      A.someMethod()  
      B.someMethod()
}

您可以在多个变量的情况下用作或语句时使用

when(null) {
  a, b -> return  //for your case of nested properties try something like "obj.a, obj?.a?.b"
  else -> doSomethingWhenAAndBAreNotNull()
}
//or do something when a and b are not null here so you don't need to nest

另一个选项可能是写类似的东西

fun <A, B> A?.and(that: B?, block: (A, B) -> Unit) {
    this?.let { a -> that?.let { b -> block(a, b) } }
}

然后像这样使用

var first: Int?
var second: Int?
first.and(second) { f, s -> someFunction(f,s) }

相关内容

  • 没有找到相关文章