为了账号安全,请及时绑定邮箱和手机立即绑定

重拾Kotlin(9)-空安全

一、空安全

1.1、可空性

在 Kotlin 中,类型系统区分一个引用是可以容纳 null (可空引用)还是不能容纳(非空引
用)。 例如,String 类型的常规变量不能指向 null

    var name: String = "leavesC"
    //编译错误
    //name = null

如果希望一个变量可以储存 null 引用,需要显式地在类型名称后面加上问好来标记它:

    var name: String? = "leavesC"
    name = null

问号可以加在任何类型的后面来表示这个类型的变量可以存储 null 引用:Int?、Doubld? 、Long? 等

Kotlin 对可空类型的显式支持有助于防止 NullPointerException 导致的异常问题,编译器不允许不对可空变量做 null 检查就直接调用其属性

fun check(name: String?): Boolean {
    //编译器不允许不对 name 做 null 检查就直接调用其属性
    return name.isNotEmpty()
}

需要显式地进行 null 检查

fun check(name: String?): Boolean {
    if (name != null) {
        return name.isNotEmpty()
    }
    return false
}

1.2、安全调用运算符:?.

安全调用运算符:?. 允许把一次 null 检查和一次方法调用合并为一个操作,如果变量值非空,则方法或属性会被调用,否则直接返回 null

例如,以下两种写法是完全等同的:

fun check(name: String?) {
    if (name != null) {
        println(name.toUpperCase())
    } else {
        println(null)
    }
}
fun check(name: String?) {
    println(name?.toUpperCase())
}

1.3、Elvis 运算符:?:

Elvis 运算符:?: 用于替代 ?. 直接返回默认值 null 的情况,Elvis 运算符接收两个运算数,如果第一个运算数不为 null ,运算结果就是其运算结果值,如果第一个运算数为 null ,运算结果就是第二个运算数

例如,以下两种写法是完全等同的:

fun check(name: String?) {
    if (name != null) {
        println(name)
    } else {
        println("default")
    }
}
fun check(name: String?) {
    println(name ?: "default")
}

1.4、安全转换运算符:as?

安全转换运算符:as? 用于把值转换为指定的类型,如果值不适合该类型则返回 null

fun check(any: Any?) {
    val result = any as? String
    println(result ?: println("is not String"))
}

1.5、非空断言:!!

非空断言用于把任何值转换为非空类型,如果对 null 值做非空断言,则会抛出异常

fun main(args: Array<String>) {
    var name: String? = "leavesC"
    check(name) //7

    name = null
    check(name) //KotlinNullPointerException
}

fun check(name: String?) {
    println(name!!.length)
}

1.6、let 函数

let 函数可用于在表达式不为 null 时才执行指定代码块

fun main(args: Array<String>) {
    var name: String? = "leavesC"
    check(name) //leavesC

    name = null
    check(name) //什么都不会输出
}

fun check(name: String?) {
    name?.let {
        println(name)
    }
}

1.7、可空类型的扩展

为可空类型定义扩展函数是一种更强大的处理 null 值的方式,可以允许接收者为 null 的调用,并在该函数中处理 null ,而不是在确保变量不为 null 之后再调用它的方法

例如,如下方法可以被正常调用而不会发生空指针异常

    val name: String? = null
    println(name.isNullOrEmpty()) //true

isNullOrEmpty() 的方法签名如下所示,可以看到这是为可空类型 CharSequence? 定义的扩展函数,方法中已经处理了方法调用者为 null 的情况

@kotlin.internal.InlineOnly
public inline fun CharSequence?.isNullOrEmpty(): Boolean {
    contract {
        returns(false) implies (this@isNullOrEmpty != null)
    }

    return this == null || this.length == 0
}

重拾 Kotlin 系列文章目录: 重拾 Kotlin

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
34
获赞与收藏
119

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消