(1)空类型安全的概念
注意,在这里nonNull重新赋值为null的时候,编译会报错。这是因为前面声明的nonNull为String类型,在Kotlin中String类型为非空类型,所以当再给nonNull赋值为null的时候,编译会报错。
如果想使nonNull可以赋值为null,怎么办呢?如下操作:
var nonNull:String?="Hello"
nonNull=null
在声明的时候,在类型后面加问号?,意为变量可以为空。
但是这样写,在使用时有可能报空指针:
可以强转为不可空类型:
val length=nonNull!!.length
但是这种形式是在确定nonNull不为空的情况下,可以这样用,如果nonNull为空,那么在运行时还会报空指针异常,不够安全。
那么如何安全地书写呢?看下面这种形式:
val length=nonNull?.length
这种书写形式,无论nonNull是不是空,都不会触发空指针。只是在nonNull不为空的时候,val length=nonNull.length;在nonNull为空的时候,val length=null;
但是这种形式也有一种弊端,就是length可能为Int类型,也可能为null类型。为了使length的类型能够统一,我们可以这样写:
val length=nonNull?.length?:0 //elvis运算符
这种形式,意为如果nonNull不为空,那么val length=nonNull.length,如果nonNull为空,那么val length=0;
这样不仅保证了nonNull不会报空指针,而且保证了length的类型统一。
(2)空类型的继承关系
var x:String="Hello"
var y:String?="World"
y=x//编译成功
var x:String="Hello"
var y:String?="World"
x=y//编译失败
说明了String是String?的子集
里式替换原则:任何基类出现的地方,子类一定可以出现。
(3)平台类型
Java、JavaScript、Native
不同语言之间的调用,比如Kotlin调用Java中的代码,这时需要开发者注意,判断是否为空,例如:
在Kotlin中定义的这个title,编译器无法判断是否有可能为空。如果开发者不注意,那么当title为空的情况下去执行title.length就会报空指针。
也可以用@NotNull注解进行一下约束,但是添加了@NotNull注解的方法就不能反回null了: