空安全
- 空安全
- 可控类型和非空类型
- 在条件中检查null
- 安全掉还用
- Elvis操作符
- !!操作符
- 安全转换
空安全
可空类型和非空类型
Kotlin致力于消灭空引用:为了避免Java中的NullPointerException
(NPE)
Kotlin类型系统致力于消灭NullPointerException
,唯一可以导致NPE异常的可能是:
明确调用
throw NullPointerException
外部java代码引起
一些前后矛盾的初始化(在构造函数中没初始化的成员在其他地方使用)
在Kotlin类型系统中可以为空和不可为空的引用是不同的。比如:普通的String
类型的变量不能为空:
不可空变量的声明:var a:String="abc"
可空变量声明:var b:String?="abc"
在条件中检查null
首先,你可以检查b
是否为空,并且分开处理下面的选项:
val l = if (b != null) b.length() else -1
编译器会跟踪你检查的信息并允许在if中调用length()。更复杂的条件也是可以的:
if (b != null && b.length() >0)
print("Stirng of length ${b.length}")
else
print("Empty string")
注意只有在b是不可变时才可以
安全调用
第二个选择就是用安全操作符 ?.
b?.length()
如果b不为空则返回长度,否则返回空,这个表达式的类型是Int?
安全调用在链式调用是很有用的。比如
bob?.departName?,head?.name
Elvis操作符
当我们有一个r的可控引用时,我们可以说如果r
不为空就使用它,否则使用非空的x
val test:Int=if(b!=null)b.length() else -1
尽管使用if表达式可以完成目标但是最简单的是使用 Elvis操作符?:
val test=b.length()?:-1
注意在Kotlin中throw return是表达式,所以他们可以在Elvis操作符右边
//Elvis操作符
fun getElvisTest(user:TestUser):String?{
val name=user.name?:throw IllegalArgumentException("name not exist")
val age=user.age?:return null
return name
}
!!操作符
第三个选择是NPE-lovers,我们可以用b!!,这会返回一个非空的b或者抛出一个b为空的NPE
val test=b!!.length
安全转换
普通的转换可能产生ClassCastException
异常,另一个选择就是使用安全转换,如果不成功就返回空:
val test:Int?=a as? Int