移除Kotlin代码中的感叹号(!!)

空安全是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代码中常见的错误

这个可变属性在空检查后不能被改变。许多人用下面这种方式解决:

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'参数为空!"})

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java帮帮-微信公众号-技术文章全总结

Java基础-20(01)总结,递归,IO流

1:递归(理解) (1)方法定义中调用方法本身的现象 举例:老和尚给小和尚讲故事,我们学编程 (2)递归的注意事项; A:要有出口,否则就是死递归 B...

3439
来自专栏Java大联盟

23种设计模式详解(二)

1623
来自专栏一直在跳坑然后爬坑

前往kotlin的路上

官网:http://kotlinlang.org/docs/reference/ github:https://github.com/JetBrains/ko...

931
来自专栏Android开发指南

Android回调接口的写法

8925
来自专栏后端之路

dubbo源码系列之filter的前生

dubbo的filter类似于spring的aop,提供了环绕增强功能。 参考dubbo缓存代码分析 缓存是filter的一个很典型的实现。 那么filter是...

4526
来自专栏二进制文集

Java 回调机制

Teacher 中,有一个解决问题的对象:Student,在Student中解决问题之后,再通过引用调用Teacher中的tellAnswer接口,所以叫回调。

2483
来自专栏腾讯Bugly的专栏

Kotlin扩展函数与实现机制探索

2017年Google IO大会宣布使用Kotlin作为Android的官方开发语言,Kotlin作为一种新式的函数式编程语言,也有人称之为Android平台的...

5246
来自专栏Ryan Miao

Java8学习(4)-Stream流

Stream和Collection的区别是什么 流和集合的区别是什么? 粗略地说, 集合和流之间的差异就在于什么时候进行计算。集合是一个内存中的数据结构,它包...

8327
来自专栏IT笔记

2016头条校招笔试题(LRU)算法之JAVA实现

操作系统中可以使用LRU(Least Recently Used)内存淘汰旧数据的策略,如果内存需要加载新数据但空间不足,则会按照最近访问时间进行排序,并将最老...

32910
来自专栏xingoo, 一个梦想做发明家的程序员

【设计模式】—— 状态模式State

  模式意图   允许一个对象在内部改变它的状态,并根据不同的状态有不同的操作行为。   例如,水在固体、液体、气体是三种状态,但是展现在我们面前的确实不同的...

1947

扫码关注云+社区