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。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值