为什么kotlin中null+null的类型隐式是String?

Why is the type of null + null implicitly String in Kotlin?

以下 Kotlin 代码:

val x = null + null

导致 x 属于 String 类型,根据 String.plus 的文档,这是正确的:

Concatenates this string with the string representation of the given [other] object. If either the receiver or the [other] object are null, they are represented as the string "null".

但是,我不明白为什么会这样 - 是因为语言的某些特殊功能吗?

可能是因为 String?.plus(Any?) 是 Kotlin 库中唯一接受可空类型作为接收者的 plus 函数。因此,当您调用 null + null 时,编译器会将第一个 null 视为 String?.

如果你定义一个扩展函数,其中接收者类型是Int?并且return类型是Int,那么x将被推断为Int.

public operator fun Int?.plus(other: Any?): Int = 1
val x = null + null

如果你在同一个文件中声明另一个类似的函数(可空类型作为接收者类型),当你调用null + null时,它会导致编译时错误:Overload resolution ambiguity. All these functions match..

public operator fun Int?.plus(other: Any?): Int = 1
public operator fun Float?.plus(other: Any?): Float = 1F
val x = null + null    //compile time error
val x = null + null

尝试将其改写如下,您会找到答案:

val x = null.plus(null)

下面是 IntelliJ 显示的 plus 方法的签名:

public operator fun String?.plus(other: Any?): String

所以第一个 null 被视为 String? 类型,然后当您尝试添加其他任何内容时,上面的 plus 方法是您唯一的匹配。打印出 x 将导致 nullnull

我们需要从Nothing的类型开始。此类型的可能值恰好为零。这是一个 bottom type, and is a subtype of every other type (not to be confused with Any, which is a supertype of every other type)。 Nothing 可以强制转换为任何类型,因此您可以执行以下操作:

fun doStuff(a: Int): String =
    TODO("this typechecks")

继续 Nothing? 的类型,意思是 Nothingnull。它有 0 + 1 个可能的值。所以 null 的类型是 Nothing?Nothing? 可以强制转换为任何可为 null 的类型,因此您可以执行以下操作:

var name: String? = null

此处null : Nothing?被强制转换为String?

出于某种原因,不幸的是,this function defined in stdlib:

operator fun String?.plus(other: Any?): String

这允许 null + null 利用我上面提到的那些强制规则