简书人物KotlinKotlin精讲-黑马程序员(原创)

kotlin精讲-第2章(8)?和?. 和!! 和?:

2017-12-04  本文已影响352人  739c8d412b4c

Kotlin相比于Java

相比于java 描述
新增 新增的null机制,有效避免空指针
增强 Kotlin代码中不会出现大量的非空判断

目标

要求 知识点
掌握 ?运算符使用
掌握 ?.运算符使用
掌握 !!运算符使用
掌握 ?: 运算符使用

Kotlin为什么引入了Null机制?Java程序员都知道,在开发过程中经常遇到空指针异常,如果不处理合理,就会引起程序的crash(崩溃)。为了尽可能的避免空指针异常的出现,Kotlin引入了Null机制。(大笑),【Kotlin相比于Java,有效避免了空指针异常】。

null机制总结起来,依靠就是把变量分为了可空类型和不可空类型。可空类型和不可空类型在变量赋值调用方面有了各自的限制。汇总如下表:

变量类型 描述 限制
非空类型 变量肯定不会为null 非空类型变量,不能赋值为null
可空类型 变量可能为null 可空类型变量,可空类型的变量不能直接使用,可以通过非空判断 ?. !!.使用

当然直接通过该表不能很好的去理解。我们可以通过“?”、“?.”、“!!.”、“?:”4个符号去理解null机制。

?(可空类型变量)

我们需要知道,Kotlin把变量分成了两种类型,一种是不可空类型,一种可空类型。变量默认是非空类型。那可空类型变量怎么定义呢?只需在变量类型后面加上一个问号,变量就变成了可空类型变量,参考代码:

针对以上代码,其中price是非空类型变量,其中age是可空类型变量。

不可空变量不能赋值为null,如果我们给price以及age两个变量都赋值为null,将出现编译错误,参考截图:

可以看到,代码提示“Null can not be a value of a non-null type String”也就是“非空类型的String不能赋值为null”。

可空类型变量不能直接使用,如果我们直接使用可空类型变量age,则会出现如下的编译错误,参考代码:

是的,编译的时候错误提示“Only safe(?.) or non-null asserted(!!.) calls are allowed ona nullable receiver of type String?”,也就是“可以通过安全调用符(?.)或者非空断言(!!.)直接去使用可空类型的变量”。 这里其实编译器帮我们提示了2种做法。其实想要使用可空类型变量,总结起来使用3种方式的,汇总如下:

方式1:使用非空判断

方式2:使用安全操作符?.

方式3:使用非空断言!!

使用非空判断使用可空类型变量,比如针对上面代码,我们在使用age变量的时候通过非空判断去使用,参考如下:

可以看到,编译通过了。因为Kotlin约定“如果一个变量,进行了非空判断,该变量的类型就变成了非空类型。”也就是经过了代码的9行,到了代码的10行,编译器会认为age变量是不可空类型变量了。

虽然非空判断,就可以使用可空类型的变量了,但是如果都用非空判断,代码里面将会出现大量的非空判断。这样的代码看起来就很像java的做法了。【Kotlin相比于Java,代码中减少了非空判断的使用】。那毫无疑问,不用非空判断,就需要用到Kotlin提供的安全调用符或者非空断言。

?.****(安全调用符)

安全调用符的出现为了解决什么问题?可空类型变量不能直接使用,但是直接使用非空判断又过于复杂,所以可以使用安全调用符。

怎么使用安全调用符?之前的结构是【变量.方法】,现在的结构是【变量?.方法】。

使用了安全调用符,代码执行逻辑是怎样的?变量不会NULL的时候,才去执行方法,所以不会报空指针。变量为NULL的时候,【变量?.方法】的结果为NULL,参考下图:

其实可以把安全调用符看做是if非空判断的简写形式,也就是varresult = if (age != null) age.toInt() else null等同于var result = age?.toInt()


!!.(非空断言)

非空断言的出现为了解决什么问题?可空类型变量不能直接使用,但是直接使用非空判断又过于复杂,所以还可以使用非空断言。怎么使用非空断言?之前的结构是【变量.方法】,现在的结构是【变量!!.方法】。

使用非空断言,代码执行逻辑是怎样的?变量不为NULL的时候,执行方法,变量为NULL的时候,抛出异常,参考下图:

如果变量age为null



可以看出,代码走到15行的时候就抛出异常了,15行后面的代码没有执行了。
如果变量age不为null


安全调用符和非空断言如何选择?

  1. 从安全角度,安全调用符比非空断言更加安全。变量为NULL的时候,使用安全调用符不会抛出异常,使用非空断言,会抛出异常。

  2. 非空断言的做法是不推荐的##,一个可空类型变量,加上非空断言,可以理解为开发者就是认定一个可空的变量为非空的,这显得有些霸道,不够和谐(大笑)。

?:( Elvis操作符)

针对【变量?.方法】,如果变量为NULL,【变量?.方法】的返回结果是NULL,那我们能不能指定想返回的值呢?答案是肯定的,我们需要配合Elvis操作符,使用方式为【变量?:值 】。参考代码:

上一篇 下一篇

猜你喜欢

热点阅读