Kotlin基础(8)-->空指针检查

一、可空类型系统

Kotlin默认所有的参数和变量都不可为空。
Int 表示不可为空的整型
Int? 表示可为空的整型
eg:

fun doStudy(study: Study?) {
        if (study != null) {
            study.doHomeWork()
            study.readBook()
        }
    }

有点啰嗦吧,别急,Kotlin还提供了一系列辅助工具帮我们作判空处理。

二、判空辅助工具

1. ?.操作符

表示当对象不为空的时候正常调用相应的方法,当对象为空的时候什么都不做。
使用 ?.操作符改变上面代码:

fun doStudy(study: Study?) {
        study?.doHomeWork()
        study?.readBook()
    }
2. ?:操作符

这个操作符左右两边都接收一个表达式,如果左边的表达式的结果不为空就返回左边表达式的结果,否则就返回右边表达式的结果。

    //原代码
    var c = if (a != nul) a else b

    //使用?:操作符
    var c = a ?: b
3. !!操作符

Kotlin也不是特别的智能,有时候我们逻辑上已经将空指针异常处理了,单Kotlin编译器并不知道,那么这个时候还是会编译失败,比如以下例子:

var content: String? = "hello"
fun main() {
    if (content != null) {
        printUpperCase()
    }
}

fun printUpperCase() {
    val toUpperCase = content.toUpperCase()
    print(toUpperCase)
}

这段代码逻辑没问题,但是一定无法执行。因为printUpperCase()函数并不知道外部已经对content做了非空检查,所以在调用toUpperCase()时,还认为存在空指针方风险。
使用!!操作符:

fun printUpperCase() {
    val toUpperCase = content!!.toUpperCase()
    print(toUpperCase)
}

这是一个种有风险的写法,意在告诉Kotlin,我非常确信这里的对象不会是空,所以不用你来做非空检查了,如果出现问题,可以直接抛出空指针异常,后果我自己承担。

4. let函数

let既不是操作符也不是关键字,是一种函数。这个函数提供了函数式API的编程接口,并将原始调用对象作为参数传递到lambda表达式中,示例代码:

obj.let { obj2 ->
  //编写具体的业务逻辑
}

obj与obj2是一个对象。
let函数配合?.操作符做空检查:

 fun doStudy(study: Study?) {
        study?.let { stu ->
            stu.readBook()
            stu.doHomeWork()
        }
    }

这样我们对study对象只做了一次非空判断就可以使用了。
优化之后:

 fun doStudy(study: Study?) {
        study?.let { 
            it.readBook()
            it.doHomeWork()
        }
    }

另外,let函数是可以处理全局变量的判空问题的。而if无法做到这一点。