Kotlin- 空安全(Null Safety)

来源:互联网 发布:手机淘宝贷款 编辑:程序博客网 时间:2024/06/08 12:38

可为空的类型和非空类型

Kotlin的类型系统旨在消除在代码中引用空引用的危险。

在很多语言中都有一个陷阱,包括Java,访问空引用的成员就会导致空引用异常,在java中就是等价于NullPointerException异常.

Kotlin的类型系统会在我们的代码尽量消除空指针异常,引起空指针异常的情况可能是以下这些情况:
- 明确的抛出空指针异常
- 使用接下里描述的!!操作符
- 外部的Java代码引起的空指针异常
- 初始化的时候有些数据不一致导致

在Kotlin中,类型系统会区别哪些引用可为空(可为空的引用),哪些不可为空(不可为空的引用),例如,一个正常的String变量就是不可能为空:

va a:String = "aa"a = null //编译错误

如果要允许为空,我们声明可为空的字符串是用String?类型:

var b : String? = "abc"b = null //ok

现在,如果你调用a的方法或属性,它就不会引起空指针异常,因此你可以说它是安全的:

val l=a.length

但是如果你想访问b的方法或属性,它就不是安全的,并且编译器还会抛出异常:

val l = b.length //错误,变量b为 'null'

但是我们还是可以访问这个属性,不过一般情况下不会这么做。

用条件语句检查非空

首先,如果你要明确检查b是否非空,这里有两种可选方式选择:

val l = if(b != null) b.length else -1

编译器会在执行的时候记录详细信息,会跟进if条件来判断是否执行length,这里还有一个复杂的条件判断:

if (b != null && b.length > 0) {    print("String of length ${b.length}")} else {    print("Empty string")}

==注意,这种方式只有在b是不可更改的情况下才有效,因为它在检查是否非空的时候有可能在其他地方被修改了==

安全调用

对于安全使用,这里有第二个选择是安全调用,那就是用’?.’:

b?.length

如果b不为空的情况下就返回b.length,为空就进行其他处理,这个表达式的类型是Int?。

安全调用在一系列的调用是非常有用的,例如,如果Box是一个职员,可能需要赋值到一个部门中(有可能不需要),这个部门中可能有一个头,然后我们一定要获得这个头的名字,那么我们就可以这样写:

bob?.department?.head?.name

在这一系列中,只要有一个为空就返回空

如果是只执行非空值的某个操作,你可以配合let来使用安全调用操作:

val listWithNulls: List<String?> = listOf("A", null)for (item in listWithNulls) {     item?.let { println(it) } // 忽略null,打印A}

艾维斯操作符(Elvis Operator)

当我们有一个可为空的r引用,我们可以说”如果r不为空就使用,否则就用一些非空值x”:

val l: Int = if (b != null) b.length else -1

连同完整if表达式,我们可以使用艾维斯操作符’?:’来表述:

val l =b?.length ?: -1

如果’?:’左边的表达式不为空,艾维斯操作符就返回它,否则就返回右侧的表达式,这里需要注意的是右侧的表达式只有在左侧表达式为空的情况下才会发生

==注意,因为在艾维斯操作符的右边可以抛出异常和返回值,这可能非常方便,例如检查函数参数:==

fun foo(node: Node): String? {    val parent = node.getParent() ?: return null    val name = node.getName() ?: throw IllegalArgumentException("name expected")    // ...}

‘!!’操作符

对于空指针还有第三种选择,我们可以写成’b!!’,它依然会返回b的非空值或者当b为空的时候抛出空指针:

val l = b!!.length

另外,如果你想要空指针,你也可以有,但你必须明确的要求才会抛出空指针,并且它还不是突然出现。

安全转型

如果这个对象不是目标类型的话就会导致ClassCastException异常,当前还有另外一个选择就是在类型转换失败的时候返回空。

val aInt: Int? = a as? Int

可为空类型的集合

如果你有一个元素可为空的集合,并且你想去筛选出非空元素,那么你就直接用filterNotNull:

val nullableList: List<Int?> = listOf(1, 2, null, 4)val intList: List<Int> = nullableList.filterNotNull()
原创粉丝点击