kotlin:扩展方法和空接收器

kotlin: extension methods and null receiver

在 lombok 扩展方法中 obj.method()SomeUtil.method(obj) 的语法糖。它允许 obj 为空。

Kotlin 扩展方法是静态解析的,所以我假设它是相同的语法糖。但是当我写

fun Any.stringOrNull() = this?.toString()

我收到关于非空接收器上不必要的安全调用的警告。这是否意味着我不能像使用 Lombok 那样在空对象上调用扩展函数?

如果将它定义为可空类型的扩展,则可以在可空对象上调用它:

fun Any?.stringOrNull() = ...

否则,与任何其他方法一样,您必须使用 safe call operator

您可以在可为空的接收器类型上创建扩展。在您的示例中,它必须是 Any? 而不是 Any ,后者不允许为空,请参阅 docs:

Nullable Receiver

Note that extensions can be defined with a nullable receiver type. Such extensions can be called on an object variable even if its value is null, and can check for this == null inside the body. This is what allows you to call toString() in Kotlin without checking for null: the check happens inside the extension function.

fun Any?.toString(): String {
    if (this == null) return "null"
    // after the null check, 'this' is autocast to a non-null type, so the toString() below
    // resolves to the member function of the Any class
    return toString()
}

val string: String? = "Hello World!" print(string.length)
// Compile error: Can't directly access property of nullable type. print(string?.length)
// Will print the string's length, or "null" if the string is null.

?. 可空接收者的安全调用运算符##

安全调用运算符 returns 如果左边的值为空,则为 null,否则继续计算右边的表达式,因此为了调用可空接收器上的任何函数,您需要使用安全调用Any 之后的运算符。(使用 Any?) 然后你可以在函数内部检查 this(此处 this object points to receiver)的空值 body.This 是什么允许你在 Kotlin 中调用 toString() 而不检查空值:检查发生在扩展函数内部。

fun Any?.toString(): String {
    if (this == null) return "null"
    // after the null check, 'this' is autocast to a non-null type, so the toString() below
    // resolves to the member function of the Any class
    return toString()
}

小心,因为:

fun Any?.toString(): String

以下行为:

var obj: Any? = null

obj?.toString() // is actually null
obj.toString() // returns "null" string

刚刚花了 15 分钟非常沮丧才意识到这一点...