移除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 条评论
登录 后参与评论

相关文章

来自专栏IT可乐

Java数据结构和算法(六)——前缀、中缀、后缀表达式

  前面我们介绍了三种数据结构,第一种数组主要用作数据存储,但是后面的两种栈和队列我们说主要作为程序功能实现的辅助工具,其中在介绍栈时我们知道栈可以用来做单词逆...

1929
来自专栏码神联盟

碎片化 | 第四阶段-46-值栈valueStack介绍和原理-视频

如清晰度低,可转PC网页观看高清版本: http://v.qq.com/x/page/q0567vth0ol.html ValueStack 值栈:(接口) ...

33917
来自专栏宋凯伦的技术小栈

分享调用Java private方法

上周在修复bug时,发现Java类中某方法是private,且类中没有用到,第一感觉是方法多余。其实通过分析,发现原来Native Code会通过JNI调到此方...

1715
来自专栏Java技术栈

跟我学 Java 8 新特性之 Stream 流基础体验

Java8新增的功能中,要数lambda表达式和流API最为重要了.这篇文章主要介绍流API的基础,也是流API系列的第一篇文章,话不多说,直奔主题.

1003
来自专栏Python小屋

Python内置函数iter()语法及应用

iter()函数用来返回指定对象的迭代器,有两种用法:iter(iterable)和iter(callable, sentinel),前者要求参数必须为序列或者...

3526
来自专栏企鹅号快讯

教您最简单粗暴的MATLAB入门级爬虫2

感谢吴老师的《数据新闻与网络数据挖掘》课程 感谢各位捧场的小伙伴们 本文适用对象为编程零基础者 仅供学习交流使用,请勿用于商业用途。 通过这样的方法,可以类似得...

1816
来自专栏IMWeb前端团队

快速优雅的为React组件生成文档

在开发React组件时我们通常需要处理2个问题: 实例化这个组件以便调试 为这个组件编写使用文档以便更好的让别人知道怎么使用这个组件 最原始的方法莫过于开发时建...

2978
来自专栏京东技术

Vue拖拽组件开发实例

vue是一套用于构建用户界面的渐进式框架。可以用他来封装单文件组件来开发更为复杂的单页应用。 本文主要是通过封装一个拖拽组件的例子,来分析Vue组件化相关知识。

65713
来自专栏james大数据架构

Android中include标签的使用

在Android的开发中,我们知道布局文件可以让我们很方便的对各个UI控件进行位置安排跟属性设置,而在程序中可以直接取得控件并赋予对应操作功能。但是,如果是一个...

1966
来自专栏点滴积累

PhiloGL学习(3)——程序员的法宝—键盘、鼠标

前言 上一篇文章中介绍了如何让对象动起来,本文介绍如何让场景响应我们的鼠标和键盘以控制场景的缩放及对象的转动和移动等。 一、 原理分析 有了上一篇文章的基础,我...

3357

扫码关注云+社区