欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Kotlin中 ? 和 !! 的区别,?和?:使用

程序员文章站 2024-03-14 23:09:47
...

Kotlin中 ? 和 !! 的区别

前言:

Kotlin中 ? 和 !! 的区别,?和?:使用
很早就听说Kotlin对java NullPointerException有一定的管理,而在Kotlin中 ?!! 均是和 NullPointerException有关系,对于刚接触Kotlin的初学者了来说就有一点蒙,就比如我,经常能看到代码中出现很多 ? ,看着我也满脸问号。
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。