记得刚开始学Android的时候经常遇到程序因为 NullPointerException
而崩溃的情况,后来工作以后第一家公司带我们的师傅告诫我们在写代码引用对象的时候最好加上 if(a!=null)
的非空判断来避免程序空指针崩溃。但是有时候还是难免会忘记,而Kotlin语言的一大特性就是空安全的。最近又遇到了一个空指针的bug,刚好最近在用Kotlin 开发,如果我以后的项目都有Kotlin开发,那是否能够彻底的避免空指针呢 ?
在进入正文之前,带着几个疑问去解析:
1、Kotlin 如何做到空安全 ?
2、Kotlin 中的 ?和 !! 有什么区别 ?
3、Kotlin 中的 ?和 !! 适用场景分别是什么 ?
1、Kotlin 如何做到空安全 ?
我们知道Kotlin 中声明变量的方式通常需要声明为可空和非空:
var downloadTask: DownloadTask? = null
var downloadTask: DownloadTask = DownloadTask(this)
如果我们用对象 downloadTask的方法比如 downloadTask.execute(downloadUrl)
,我们发现编译器会报错提醒:
Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Int?
这就是Kotlin的空安全,编译器会检查可能为空的情况。这句话的意思是只有 空安全操作符 ?和 !! 才被允许这样写。
如果们我们改成就好了:
downloadTask?.execute(downloadUrl)
或者
downloadTask!!.execute(downloadUrl)
2、Kotlin 中的 ?和 !! 有什么区别 ?
Kotlin中 ?
表示对象是否为空,我们在使用这种声明的时候可以赋值为null
!!
表示对象为非空的类型,使用此符号,编译器会认为这个对象是非空的,从而跳过空检测
如果上述对象downloadTask 没有实例化,使用空安全访问操作符 ?
, 程序执行到这一行会直接跳过,类似于java 中的非空判断:
if (downloadTask!=null){
downloadTask.execute()
}
而使用 !!
,编译器不会报错,但是程序执行到这一行就会直接报错:
05-05 17:56:58.964 8652-8652/com.jmgo.downloaddemo E/AndroidRuntime: FATAL EXCEPTION: main Process: com.jmgo.downloaddemo, PID: 8652 kotlin.KotlinNullPointerException at com.jmgo.downloaddemo.MainActivity.onClick(MainActivity.kt:50)
这里和java中的空指针是一样的,这里面我产生了一个疑问,既然这里和java中的一样,那这个 !!
字符又有什么作用呢,这里面怎么体现 Kotlin的空安全呢,这里面就是要展开第三个问题了。
3、Kotlin 中的 ?和 !! 适用场景分别是什么 ?
看下这段代码
var list:ArrayList<String>?=null
...
if (list?.size>10){
//do something
}
...
编译器会提醒:
Operator call corresponds to a dot-qualified call 'list?.size.compareTo(10)' which is not allowed on a nullable receiver 'list?.size'.
意思是说这里list 可能为null,不允许null 和Int 比较。改成:
var list:ArrayList<String>?=null
if (list!!.size>10){
//do something
}
这里我们也可以使用 Elvis operator( ?: )
操作符,改成这样:
var list:ArrayList<String>?=null
if (list?.size ?: 0>10){
//do something
}
上述例子是需要用到 !!
的,但是实际开发中我们是很少使用 !!
的,因为这样子程序遇到空指针就会崩溃,不能体现空安全,我查了一下Kotlin的开发手册,上面是这么说的:
这里面说Null类型在大多数情况下我么是不需要使用的,所以我们用之前需要做一个非空的判断,类似于java
但是如果我们确定使用的变量一定非空,我们就可以使用 **!!
**
但是满屏的 !!感觉是不是有点怪,Kotlin的开发文档是说以后可能会和非空注释一起使用,好吧,原来是这样子~~~
好了,到这里,本篇文章就结束了,总结一下就是:大多数情况下我们需要用 空安全访问操作符 ? 配合非空判断if (a!=null)一起使用,,如果在特定的情况下我们确定对象一定不为null,或者为null 时不能让程序继续执行下去我们就用 !!
但是这里面我有一个疑问了,如果使用 ?
,程序不会报错,但是可能如果代码很多的话不方便排查到底是什么什么导致的,这里,同学们有什么看法呢 ?