为什么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?
的类型,意思是 Nothing
或 null
。它有 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
利用我上面提到的那些强制规则
以下 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?
的类型,意思是 Nothing
或 null
。它有 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
利用我上面提到的那些强制规则