当我们把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: String
override 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<Int>()
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使用的也是非空类型,使用起来更方便了。源码在此下载

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

Kotlin如何避免“!!”(非空断言)相关推荐

  1. Kotlin——初级篇(六):空类型、空安全、非空断言、类型转换等特性总结

    在我们熟知的Java中,定义一个变量可以默认不赋值,因为Java的系统会给我们默认赋一个默认值,并且Java可定义一个赋值为null的变量,这样在使用这个变量的时候都会去显示判断该变量是否为null. ...

  2. TypeScript Non-null Assertion Operator 非空断言操作符 - 感叹号

    TypeScript 也有一种特殊的语法,可以在不进行任何显式检查的情况下从类型中删除 null 和 undefined. 写作 ! 在任何表达式实际上是一个类型断言之后,该值不为空或未定义: fun ...

  3. TypeScript的非空断言操作符(感叹号)

    x! 将从 x 值域中排除 null 和 undefined. 看个例子: myFunc = (maybeString: string | undefined | null) => {const ...

  4. kolin学习笔记:非空类型与可空类型

    记得在我一开始接触kotlin时,听到的最多的就是kotlin的类型安全,各种巴拉巴拉?,关键就不断的夸安全,其他的却是什么也没有解释,差点还没入门,就直接放弃.虽然确实这是kotlin的特性之一,但 ...

  5. 【Kotlin】变量简介 ( 可空类型 | lateinit | 初始化判定 | 非空类型 | !! 与 ? 修饰符 | ?= ?. ?: 运算符 | 抽象属性变量)

    文章目录 I . Kotlin 变量总结 II . Kotlin 非空变量 III . 非空变量不能赋空 IV . lateinit 关键字 V . lateinit 初始化判定 VI . Kotli ...

  6. Kotlin一大特色之空安全

    前言 kotlin是谷歌推出的Android开发的又一支持语言,没办法,程序猿就是不停的学习.过了一遍基础以后,记录一些kotlin的一些特点. 可空类型与非空类型 在 Kotlin 中,类型分为可空 ...

  7. ASP.NET中 RequiredFieldValidator(非空验证)的使用

    ylbtech-ASP.NET-Control-Validator: RequiredFieldValidator(非空验证)的使用 ASP.NET中 RequiredFieldValidator(非 ...

  8. oracle判断非空并拼接,oracle sql 判断字段非空,数据不重复,插入多跳数据

     oracle sql 判断字段非空,数据不重复 select distinct(mobile) from wx_user_mobile where active_time is not null ...

  9. 还在用if(obj!=null)做非空判断?带你快速上手Optional实战性理解!

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 1.前言 相信不少小伙伴已经被java的NPE(Null ...

最新文章

  1. cx oracle 返回码,oracle错误代码处理cx_oracle
  2. python动态参数_python动态参数
  3. ASP.NET定时调用WebService 运行后台代码
  4. Java代码服务器上下载图片_Java如何从服务器中下载图片
  5. Python错误:TypeError: string indices must be integers
  6. Modbus​协议​深入​讲解_NI
  7. JAVA-date(计算时间差)
  8. java删除文件中的一行_在Linux中使用java和javac命令编译运行java文件
  9. ES6新特性_ES6模块化介绍_优势_以及产品---JavaScript_ECMAScript_ES6-ES11新特性工作笔记041
  10. 社区实施 GPL 的原则介绍
  11. CISCO寄存器配置与说明
  12. 拓端tecdat|R语言时间序列分解和异常检测方法应用案例
  13. python实现自动打电话软件_python拨打电话
  14. Coursera学科分类爬虫实例介绍
  15. 工具 - 文本比较/对比 - 收集
  16. 【Web前端】HTML—6.表单标签
  17. linux账号与群组
  18. java闭锁_Java闭锁_CountDownLatch
  19. 华为,工资岗位揭秘 2010年08月02日
  20. 合肥工业大学2021离散数学上机实验一

热门文章

  1. mysql获取有哪几种状态_Mysql进阶垫脚石 -- Sql命令的执行状态有哪几种
  2. 我愿意参加计算机俱乐部的英文,如果你是一英语俱乐部的负责人你会组织什么活动...
  3. instagram api java_如何在没有用户交互的情况下获得instagram access_token(新api)?...
  4. python实操培训_python实训day1
  5. restore还原不同名称的数据库_SQL Server2005还原数据库攻略
  6. 网络通信基础知识普及篇
  7. 在线学html5,HTML5 在线学习自我演进的导弹系统
  8. python爬虫超时重试_Python爬虫实例(三):错误重试,超时处理
  9. python list倒序_Python基础-不一样的切片操作
  10. 高速串行总线的设计基础(一)同步时序模型介绍