kotlin:如果值为空则退出,否则将该值用作不可空值

kotlin: If value is null then exit, else use that value as not nullable

基本上这就是标题。我有一个可能为空的值。如果是,我只想退出并显示一条消息。如果它不为空,那么我需要用这个值做大量的工作。

我发现了类似的情况,但不完全是这种情况。正是这种细微差别让我抓狂。这是我在 java:

中的代码
    if (value == null) {
        print("error!");
        return;
    }

    print(value);
    doFunStuff(value);
    etc(value);

所有使用 value 的方法都要求它是 non-null。

但我很难在科特林中解决这个问题。在我尝试的所有方法中,编译器仍然坚持认为 value 仍然可以为 null,并拒绝在函数中使用它。

执行这种非常常见的代码流的 kotlin 方法是什么?

如果您的方法确实有非空参数,Kotlin 编译器应该足够聪明,可以从 Object?.

智能转换为 Object
fun yourMethod(value: Object?) {
    if (value == null) {
        print("error!")
        return
    }

    print(value) // Smart cast happens here
    doFunStuff(value)
    etc(value)
}

fun print(value: Object) {
    // Implementation
}

fun doFunStuff(value: Object) {
    // Implementation
}

fun etc(value: Object) {
    // Implementation
}

但您也可以使用 !! 运算符强制转换(尽管在这种情况下编译器会告诉您没有必要):

fun yourMethod(value: Object?) {
    if (value == null) {
        print("error!")
        return
    }

    val nonNullValue = value!!

    print(nonNullValue)
    doFunStuff(nonNullValue)
    etc(nonNullValue)
}

fun print(value: Object) {
    // Implementation
}

fun doFunStuff(value: Object) {
    // Implementation
}

fun etc(value: Object) {
    // Implementation
}

那么,您是否已经尝试过类似的操作,而这不是您所期望的?

value?.let { nonNullValue ->

   print(nonNullValue);
   doFunStuff(nonNullValue);
   etc(nonNullValue);

}

基本上 let 块中的代码只有当值不是 null.

时才会 运行

如果您的值是局部变量或函数参数,则不会出现此问题,因为编译器会将其智能转换为 not-null。

因此,我假设 value 在这种情况下是成员 属性。

方案一是复制到局部变量在函数中使用:

val value = value
if (value == null) {
    print("error!")
    return
}

print(value)
doFunStuff(value)
etc(value)

选项 2 是使用 letalso 范围函数来做同样的事情,但这在这里可能不是一个好的选择,因为太多的代码会嵌套。这在您仅使用该对象调用一个或两个函数时更有用,在这种情况下,您甚至不必为它命名(只需将其命名为 it)。

value.let { value ->
    if (value == null) {
        print("error!")
        return
    }

    print(value)
    doFunStuff(value)
    etc(value)
}

如果你的整个函数都使用这个属性,你可以避免像这样的嵌套问题,如果你不介意它返回除 Unit:

之外的东西
fun foo() = value.also { value ->
    if (value == null) {
        print("error!")
        return
    }

    print(value)
    doFunStuff(value)
    etc(value)
}

方案三是每次使用都断言非空,但是这样很丑陋。只有当您知道 属性 只能从调用此函数的同一线程访问时,这才是安全的。

if (value == null) {
    print("error!")
    return
}

print(value!!)
doFunStuff(value!!)
etc(value!!)