移除Kotlin代码中的感叹号(!!)
2018-01-04 本文已影响1054人
Kotyo
空安全是Kotlin提供的功能之一。它让你思考语言级别的可空性,所以你可以避免在Java中很常见的NullPointerException。但是,当你自动将Java代码转换为Kotlin时,你会看到很多!!符号。这意味着“你在这里有一个潜在的未处理的KotlinNullPointerException”。
下面介绍几种方式可以去避免使用!!
① 使用val而不是var
Kotlin让你在语言层面思考不可变性。val是只读的,var是可变的。建议你尽可能多的使用只读属性。它们是线程安全的,并且在函数式编程中很好用。
② 使用lateinit
有时候,我们不能使用不可变属性。这在Android中很常见。对于这种情况,我们使用Kotlin提供的lateinit。
!!的写法
private var mAdapter: RecyclerAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mAdapter = RecyclerAdapter(R.layout.item_data)
}
fun updateData() {
mAdapter!!.notifyDataSetChanged()
}
lateinit写法
private lateinit var mAdapter: RecyclerAdapter<>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mAdapter = RecyclerAdapter(R.layout.item_data)
}
fun updateData() {
mAdapter.notifyDataSetChanged()
}
注意:访问非初始化lateinit属性将导致UninitializedPropertyAccessException。
lateinit不能应用于原始数据类型(例如:Int)。对于原始数据类型,我们可以这样使用委托:
private var mNum:Int by Delegates.notNull <Int>()
③ 使用let函数
下面是Kotlin代码中常见的错误
![](https://img.haomeiwen.com/i2726727/31b01952ad67bdeb.png)
这个可变属性在空检查后不能被改变。许多人用下面这种方式解决:
private var mPhotoUrl: String? = null
fun uploadClicked() {
if (mPhotoUrl != null) {
uploadPhoto(mPhotoUrl!!)
}
}
但是可以用let函数更优雅的解决这个问题:
private var mPhotoUrl:String?=null
fun uploadClicked(){
mPhotoUrl?.let{uploadPhoto(it)}
}
④ 创建全局函数来处理更复杂的内容
let是一个简单的空检查的替代品,但是会有更复杂的情况。如:
if(name!=null&&address!=null{
upload(name!!,address!!)
}
你可以嵌套两个let,但是可读性会很差。这时候我们用下面这种方式来写:
ifNotNull(name,address){
name,address->upload(name,address)
}
封装的方法
fun <T1,T2> ifNotNull(value1:T1?,value2:T2?,bothNotNull:(T1,T2)->(Unit)){
if(value1!=null&&value2!=null){
bothNotNull(value1,value2)
}
}
⑤ 使用?:操作符
fun getName():String{
if(name!=null){
return name!!
}else{
return "android coder"
}
}
替代的方法:
fun getName():String{
return name?:"android coder"
}
⑥ 自定义错误信息
使用内置函数requireNotNull或checkNotNull处理异常信息。
upload(intent.getStringExtra("address")!!)
替代方法:
upload(requireNotNull(intent.getStringExtra("address"),{"'address'参数为空!"})