博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Kotlin如何避免“!!”(非空断言)
阅读量:6938 次
发布时间:2019-06-27

本文共 2488 字,大约阅读时间需要 8 分钟。

当我们把Java自动转成Kotlin的时候,代码里会出现很多非空断言!!。或者某些场景下因为IDE提示或编译错误,也让我们自己加上了一些!!

但使用!!的后果是有可能抛出IllegalArgumentException:Parameter specified as non-null is null

如何避免!!

使用?.let/?.apply/?.run

这种是最常用的方法,也是首选的方法。但当有多个变量同时要判空时,或者需要处理为null时的逻辑,这种方式稍微有一点麻烦,下面会讲到一些新的方式。

disposable?.let {    if (!it.isDisposed) it.dispose()}

用Val替代Var

var mutableString:String? = nullfun run() {    mutableString = "a"    printText(mutableString)}fun printText(text: String) {    ...}

此时会报错`Smart cast to 'String' is impossible, because 'multableString' is a mutable property that could have been changed by this time

:app:compileDebugKotlin FAILED`。由于multableString是Var变量,为了避免多线程对变量的修改而出现Null的情况,kotlin从编译上进行了限制。

  • 解决方法1是把var变量改为val变量
val mutableString:String = "a"fun run() {    printText(mutableString)}
  • 解决方法2是写一个新的val变量,将var变量赋值给它,将val作为参数
fun run() {    mutableString = "a"    val string = mutableString ?: ""    printText(string)}

<!-- more -->

使用Elvis操作符

fun run() {    multableString = "a"    printText(multableString ?: "")}

声明lateinit

使用lateinit声明到变量上,表示这个变量延迟初始化,比较适合在Activity.onCreate这种有生命周期的方法里初始化。

lateinit var mutableString: Stringoverride fun onCreate(savedInstanceState: Bundle?) {    multableString = "a"    printText(mutableString)}
需要注意的是,访问未初始化的 lateinit 修饰的属性会抛出UninitializedPropertyAccessException异常

注意:基本类型是不能使用lateinit的。会抛错'lateinit' modifier is not allowed on properties of primitive types

lateinit var mutableInt: Int

代理属性

如果需要对基本类型等做非空处理,可以使用代理属性。

var mutableInt: Int by Delegates.notNull
()override fun onCreate(savedInstanceState: Bundle?) { mutableInt = 1}

一定要在初始化赋值之后才能读取mutableInt,不然会抛IllegalStateException:Property ${property.name} should be initialized before get.

空与非空处理

val result = multableString.notNullElse {    "$it is not null"} ({ "is null" })

新开发的方法notNullElse,对单个变量判空处理,非空时传入it为非空类型,提高了便捷性,为空时使用第二个block来返回值。适合那里需要判空,返回值result也是非空的类型,比较实用。

多个值非空

private var mLinearLayout: LinearLayout? = null...private fun initView(context: Context) {    mLinearLayout = LinearLayout(context)}...if (tvItem == null) {    mLinearLayout!!.addView(childTvItem)} else {    mLinearLayout!!.addView(childTvItem, mLinearLayout!!.indexOfChild(tvItem) + 1)}

当我们要对多个值判断的时候,let就不那么好用了,但如果不使用let就拿不到非空的类型,像上面要判断2个都不为空时做操作,为空时另外一个逻辑。其实一早我们就已经判断空了,有没有更好的方法呢?

allNotNullElse(tvItem, mLinearLayout) { a, b ->    b.addView(childTvItem, b.indexOfChild(tvItem) + 1)} ({ mLinearLayout?.addView(childTvItem) })

新开发的方法allNotNullElse返回的a, b 两个值已经是非空类型了,这样addView使用的也是非空类型,使用起来更方便了。

喜欢这篇文章,请点赞收藏,谢谢!

转载地址:http://idbnl.baihongyu.com/

你可能感兴趣的文章
赛门铁克发现新的APT组织Gallmaker,目标锁定全球政府、军事和国防机构
查看>>
Spring Cloud-honghu Cloud分布式微服务云系统--云架构代码结构构建
查看>>
linux下5秒创建rhel7虚拟机
查看>>
Xpath语法
查看>>
JAVA-给想学JAVA的小伙伴一小点点基础
查看>>
OpenResty + Lua 访问Redis
查看>>
11.2 Apache虚拟主机
查看>>
移动APP及游戏推广,有预算为什么还起不了量
查看>>
AI芯片独角兽诞生!地平线完成6亿美金左右B轮投资
查看>>
2019年大数据发展将走向何方
查看>>
中国六个漂亮的古镇风景名胜区网站欣赏
查看>>
set IDENTITY_INSERT on 和 off 的设置
查看>>
javascript 基础4
查看>>
HTTPS背后的加密算法
查看>>
VMware虚拟机清除登录密码
查看>>
中国禁止电视剧插播广告 营销商受打击
查看>>
TCP连接建立和终止及TCP状态转换
查看>>
据报道微软将从明年一月份起推行Windows RT平板发行许可政策
查看>>
Linux权限命令之umask和mktemp
查看>>
objective c:循环引用
查看>>