为什么在Kotlin中隐式地使用了null + nulltypes的字符串?
以下Kotlin代码:
val x = null + null
结果x
是String
types的,根据String.plus
的文档是正确的:
将此字符串与给定[other]对象的字符串表示forms连接起来。 如果接收者或[other]对象为空,则表示为字符串“null”。
但是,我不明白为什么会发生这种情况 – 是由于语言的某些特殊function?
可能是因为String?.plus(Any?)
是Kotlin库中唯一一个接受可空types作为接收者的函数。 因此,当你调用null + null
,编译器会把第一个null
当作String?
。
如果你定义一个接收器types为Int?
的扩展函数Int?
而返回types是Int
,那么x
将被推断为Int
。
public operator fun Int?.plus(other: Any?): Int = 1 val x = null + null
如果你在同一个文件中声明了另一个类似的函数(可以是接收者types的空types),那么当你调用null + null
,会导致编译时错误: Overload resolution ambiguity. All these functions match.
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
的types开始。 该types具有完全为零的可能值。 它是一个底部types ,是每个其他types的子types(不要与Any
其他types的超types混淆)。 Nothing
都不能强制任何types,所以你可以做这样的事情:
fun doStuff(a: Int): String = TODO("this typechecks")
转到Nothing?
的typesNothing?
,意思是Nothing
或null
。 它有0 + 1个可能的值。 那么null
有一种Nothing?
。 Nothing?
可以被强制为任何可空types,所以你可以做这样的东西:
var name: String? = null
这里null : Nothing?
被强制为String?
。
出于某种原因,不幸的是, 在stdlib中定义了这个函数 :
operator fun String?.plus(other: Any?): String
允许null + null
利用上面提到的那些强制规则