Kotlin中 ? 和 !! 的区别,?和?:使用
Kotlin中 ? 和 !! 的区别
前言:
很早就听说Kotlin对java NullPointerException有一定的管理,而在Kotlin中 ? 和 !! 均是和 NullPointerException有关系,对于刚接触Kotlin的初学者了来说就有一点蒙,就比如我,经常能看到代码中出现很多 ? ,看着我也满脸问号。
正文:
先直接丢出通俗易懂的解释:
"?" : 加在变量名后,系统在任何情况不会报它的空指针异常
"!!" : 加在变量名后,如果对象为null,那么系统一定会报异常
通过java代码对比来学习:
java:
ArrayList<String> list = null;
Log.d(TAG, "----list size is " + list.size());
在这里,执行打印语句的时候,大家都知道会报NullPointerException,但是在Kotlin中,只要在list.size() 这里变为—>list?.size,打印的时候就会打印"----list size is null",而不会出现NullPointerException。
通过AS把上面的代码自动转换为kotlin:
val list: ArrayList<String>? = null
Log.d("TAG", "----List Size is ${list!!.size}")
可以看到AS自动把list.size()变成了list!!.size,但是为什么不是list?.size呢?
答: 这是因为编译器在转化时为了保证代码转化前后的一致性所造成的。换句话说,在Java上出异常的,转化到KT上,编译器任然会让他保持抛出异常,NullPointerException也是如此。
从以上可以看出,!! 加上去和之前的java代码没有什么区别,该null的地方任然会抛出异常,所以大多数情况下回使用?来检测null,轮不到!!出场。 !! 只会在你需要对某个对象进行非null判断,并且需要抛出异常的时候才会用到。
接下来说说 ? 到底怎么使用:
在声明对象时,把它跟在类名后面,表示这个类允许为null;
在调用对象时,把它跟在对象后面,表示如果为null程序就会视而不见。
举个栗子:
//这里声明一个变量,问号跟在类名的后面
var teacher:Teacher?= Teacher()
fun checkTeacher(){
//因为加了问号,所以这里teacher可以为null
teacher = null
//调用的时候加上问号,所以在这里不会抛出异常
println("${teacher?.name}")
}
如果不加上 ? :
//这里默认给teacher加上了!!,name意味着teacher不能为null
var teacher:Teacher= Teacher()
fun checkTeacher(){
//这里就已经报错了
teacher = null
// 并且编译器建议把对象后面的问号删除,因为这个对象永远不为空
println("${teacher?.name}")
}
所以加上 ? 是一种安全的写法,体现了Kotlin null safety的特性。
Kotlin的语法是真的很灵活,定义参数还可以写成这样:
val room: Room? = Room() // 先实例化一个room,并且room可以为空
val room: Room? = null // 不实例化了,开始room就是空的
val room: Room = Room() // 实例化一个room,并且room永远不能为空
val room = Room() // 和上一行代码一样,是KT最常用的简写语法
加上了 ? 就可以永远的摆脱了NullpointerException的烦恼?看下面一个栗子:
val arrayLists:ArrayList<Teacher>? =null
//arrayLists?.size这里就已经报错了
if (arrayLists?.size > 0){
println("---------")
}
运行一下就报错:Operator call corresponds to a dot-qualified call ‘arrayLists?.size.compareTo(0)’ which is not allowed on a nullable receiver ‘arrayLists?.size’.这句话大概意思就是当arrayLists为null时,他的size就返回一个“null”,但是”null“和“0”又不能比较。所以给我们提示改为:arrayLists?.size!! > 0
在运行代码就会得到NullpointerException。那么是不是也得像java一样在最外面加一个判断 if(arrayLists ! = null) 来避免这种异常呢?
答案是否定的,Kotlin中提供了一种表达式来解决这个问题:
对象A ?: 对象B
并且取消了Java中的条件表达式 ? 表达式1 : 表达式2这个三元表达式。
?: 表示的意思是,当对象A的值为null的时候,那么他就会返回后面的对象B
所以以上的代码就可以改写为:
val arrayLists:ArrayList<Teacher>? =null
if ((arrayLists?.size ?: 0) > 0){
println("---------")
}
就目前为止使,用上面的 ? 和 ?: 基本上能避免程序中出现的所有NullPointerException。
上一篇: Kotlin基本数据类型
下一篇: C#泛型类