Kotlin,执行嵌套的可空性检查时调用了错误的Elvis语句

Kotlin,执行嵌套的可空性检查时调用了错误的Elvis语句,kotlin,Kotlin,我发现在Elvis区块下方的案例中,被调用 实际上,它指的是外部可空性检查 val outer : String? = "" val inner : String? = null outer?.let { inner?.let { // do something } } ?: System.out.println("Outer else") 外部其他 将Elvis分支添加到内部可空性检查的行为符合预期: outer?.let { inner?.let

我发现在Elvis区块下方的案例中,被调用 实际上,它指的是外部可空性检查

val outer : String? = ""
val inner : String? = null

outer?.let {
    inner?.let {
        // do something
    }
} ?: System.out.println("Outer else")
外部其他

将Elvis分支添加到内部可空性检查的行为符合预期:

outer?.let {
    inner?.let {
        // do something
    } ?: System.out.println("Inner else")
} ?: System.out.println("Outer else")
内部其他


它是Kotlin bug吗?

它不是Kotlin bug
a?.let{expr}
如果

  • a为空,或
  • expr的计算结果为null
  • 将所有内容拼凑在一起,整个表达式的计算结果如下:

  • internal?.let{expr}
    的计算结果为null,因为
    internal
    为null(上面的案例1)
  • 所以
    outer?.let{…}
    的计算结果为null(上面的案例2),因为大括号内的内容的计算结果为null(项目符号11)
  • 因此,由于
    ?:
    运算符的剩余值为null(项目符号12.),因此将对外部elvis表达式求值

  • 当您在
    内部?.let{}
    之后添加elvis时,
    外部?.let{}
    不再返回null,它返回
    单位
    ,因此不会计算外部elvis。清楚吗?

    这不是kotlin的bug
    a?.let{expr}
    如果

  • a为空,或
  • expr的计算结果为null
  • 将所有内容拼凑在一起,整个表达式的计算结果如下:

  • internal?.let{expr}
    的计算结果为null,因为
    internal
    为null(上面的案例1)
  • 所以
    outer?.let{…}
    的计算结果为null(上面的案例2),因为大括号内的内容的计算结果为null(项目符号11)
  • 因此,由于
    ?:
    运算符的剩余值为null(项目符号12.),因此将对外部elvis表达式求值

  • 当您在
    内部?.let{}
    之后添加elvis时,
    外部?.let{}
    不再返回null,它返回
    单位
    ,因此不会计算外部elvis。清楚吗?

    Elvis运算符不仅用于可空性检查,它还将评估语句的结果,如果
    null
    ,它将运行第二个条件

    换句话说,如果
    internal?.let{}
    的计算结果为
    null
    (如果
    internal
    为null或
    let
    块返回null),您将得到打印结果
    Outer-else


    将Elvis运算符添加到内部块进一步证实了这一点,因为该表达式中的某些内容的计算结果似乎为null。

    Elvis运算符不仅用于可空性检查,还将计算语句的结果,如果
    null
    ,它将运行第二个条件

    换句话说,如果
    internal?.let{}
    的计算结果为
    null
    (如果
    internal
    为null或
    let
    块返回null),您将得到打印结果
    Outer-else


    将Elvis运算符添加到内部块进一步证实了这一点,因为该表达式中的某些内容的计算结果似乎为null。

    代码的行为与预期一致。在本例中,
    ?:
    运算符的左侧操作数为

    outer?.let {
        inner?.let {
            // do something
        }
    }
    
    outer
    不为空,因此将执行outer
    let
    internal
    为null,因此将不调用第二个
    let
    ,并且外部块的返回值将为null。这使得整个表达式的计算结果为null,因此执行
    ?:
    运算符的右操作数

    在第二个示例中,外部块的值计算为

    inner?.let {
        // do something
    } ?: System.out.println("Inner else")
    

    由于
    内部
    为空,
    ?:
    的右侧操作数将被调用并计算为
    单位
    ,这是外部块的值。

    代码的行为与预期一致。在本例中,
    ?:
    运算符的左侧操作数为

    outer?.let {
        inner?.let {
            // do something
        }
    }
    
    outer
    不为空,因此将执行outer
    let
    internal
    为null,因此将不调用第二个
    let
    ,并且外部块的返回值将为null。这使得整个表达式的计算结果为null,因此执行
    ?:
    运算符的右操作数

    在第二个示例中,外部块的值计算为

    inner?.let {
        // do something
    } ?: System.out.println("Inner else")
    
    由于
    内部
    为空,
    ?:
    的右侧操作数将被调用并计算为
    单位
    ,这是外部块的值