做Android开发的对NPE(NullPointerException)问题应该不会陌生,在我们公司NPE问题会归属于低级缺陷。
Kotlin针对这个问题做了改进,将空指针异常的检查提前到了编译时期,如果我们的程序存在空指针异常的风险,那么在编译的时候会直接报错,修正之后才能成功运行,这样就可以保证程序在运行时期不会出现空指针异常了。
例如:
fun main() {
val student = Student("lucy", 19)
study(null)
}
fun study(student : Student) {
student.doHomework()
}
我在调用study函数的时候塞了一个空,编译器会报错:Null can not be a value of a non-null type Study
Kotlin默认所有的参数和变量都不可为空,所以会传递null
会直接报错。可是实际开发中,有些逻辑我们需要对null
进行特别的处理。对这种需求,Kotlin提供了另外一套可为空的类型系统,我们需要在编译时期就将所有潜在的空指针异常都处理掉,否则代码将无法编译通过。
下面来学习Kotlin中可空类型系统常用的操作符。
上面的例子我们稍微改下,在study
函数的入参后面加一个?
,这样可正常传递null
对象,但是如果入参student
为空,方法doHomework()
调用提示错误,因此需要加一个空判断。
也就是说如果变量或常量后面加上?
,说明这个变量或者常量可以为空,在使用的时候需要注意。
fun main() {
val student = Student("lucy", 19)
study(null)
}
fun study(student: Student?) {
if (student != null){
student.doHomework()
}
}
fun main() {
val student = Student("lucy", 19)
study(null)
}
fun study(student: Student?) {
student?.doHomework()
}
每次判空都要加一个if
判断,太过繁琐,可以使用操作符?.
解决,这个符号表示,只有前面的对象不为空,后面的方法才能执行。
fun test(str: String?) {
val newStr: String = if (str != null) {
str
} else {
""
}
}
上面的例子可以用操作符优化下;
fun test(str: String?) {
val newStr: String = str ?: ""
}
?:
这个操作符的左右两边都接收一个表达式,如果左边表达式的结果不为空就返回左边表达式的结果,否则就返回右边表达式的结果。
多个操作符一起使用;
fun getTextLength(str: String?) = str?.length ?: 0
由于str
可能为空,因此我们在调用它的length字段时需要使用?.
操作符,而当str
为空时,str?.length
会返回一个null
值,这个时候我们再借助?:
操作符让它返回0。
fun main() {
val student = Student("lucy", 19)
study(null)
}
fun study(student: Student?) {
student.doHomework()
}
上面的例子在study
函数的入参后面加一个?
,这样study就可能为空,因此编译器会提示错误,但是如果我们确认每次调用
study
函数的入参都不为空,也可以使用!!
操作符。
fun main() {
val student = Student("lucy", 19)
study(student)
}
fun study(student: Student?) {
student!!.doHomework()
}
不过这是一种有风险的写法,编译虽然能过,但是运行时如果对象为空了会报空指针异常。