代码之家  ›  专栏  ›  技术社区  ›  Dmitry

Kotlin安全呼叫操作员使用

  •  3
  • Dmitry  · 技术社区  · 2 年前

    假设我有以下代码:

    fun main() {
        val userName: String? = "Dmitry" // line 1
        userName?.takeLast(2)?.reversed() // line 2
        userName?.plus("kotlin").plus("lang") // line 3
    }
    

    我以前不知道使用Elvis运算符的原因 reversed() -为什么不可能只使用 . ? 正如我在文档中看到的 takeLast() 始终提供 String String? 。在我的示例中,相同的场景适用于第3行-> plus() 总是返回String,所以在第二个之前不需要Elvis ?

    3 回复  |  直到 2 年前
        1
  •  3
  •   Tenfour04    2 年前

    既然有 ?. 之前 takeLast() ,结果表达式的计算结果为可为null的String。由于 userName 可以为空, takeLast() 甚至可能不会被调用,并且您只会有null进入 takeLast() 呼叫

    在最后一行中,您正在调用为可为null的String接收器定义的扩展函数,因此不需要有条件地调用它。其定义为 fun String?.plus 因此它可以在可为null的输入上直接调用。

    顺便说一句 ?. 不称为Elvis运算符。它被称为安全呼叫操作员。Elvis操作员 ?: 并且做一些不同的事情。

        2
  •  1
  •   InSync Christian C. Salvadó    2 年前

    从…起 the specs :

    a?.c 与完全相同

    when (val $tmp = a) {
        null -> null
        else -> { $tmp.c }
    }
    

    换句话说, userName?.takeLast(2)?.reversed() 与以下内容相同:

    val $tmp1: String? = when (userName) {
        null -> null
        else -> userName.takeLast(2)
    }
    val $tmp2: String? = when ($tmp1) {
        null -> null
        else -> $tmp1.reversed()
    }
    // ...and so on.
    

    上述扩展显示,每一步都可能返回 null ,这意味着有必要重复 ?. .

    至于 .plus() ,第一个 String.plus() ,而第二个 String?.plus() 。后者会治疗 无效的 作为字符串 "null" ,但第一种情况并非如此。

    如果 userName 无效的 , userName.plus() 将呼叫 一串加 。这只是因为 ?. 那个 String.plus() 改为调用。要应用相同的上述扩展:

    val $tmp: String? = when (userName) {
        null -> null
        else -> userName.plus("kotlin")  // String.plus()
    }
    $tmp.plus("lang")  // String?.plus()