浅谈Kotlin编程-Kotlin空值处理

2,243 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情

前言

许多编程语⾔(包括 Java)中最常⻅的错误之⼀,就是访问空成员会导致空异常(NullPointerException 或简称 NPE)。

开发中,经常会遇到空指针异常,如果对这个问题处理不当,还会引起程序的崩溃(crash),在Kotlin中,为了避免出现空指针异常,引入了 Null机制,本篇就来了解一下Kotlin中的 Null机制

本文总览

Kotlin空值处理.png

1. 可空类型变量(?)

Kotlin中把变量分成了两种类型

  • 可空类型变量
  • 非空类型变量

通常,一个变量默认是非空类型。若要变量的值可以为空,必须在声明处的数据类型后添加 ? 来标识该变量可为空。如下示例:

var phone: String   //声明非空变量 
var price: Int?     //声明可空变量

上述代码中,phone 为非空变量,price 为可空变量。若给变量name赋值为null,编译器会提示“Null can not be a value of a non-null type String”错误信息。引起这个错误的原因是Kotlin官方约定变量默认为非空类型时,该变量不能赋值为null, 而price 赋值为null,编译可以通过。

声明可空变量时,若不知道初始值,则需将其赋值为null,否则会报“variable price must be initialized”异常信息。

通过一段示例代码来学习如何判断变量是否为空,以及如何使用可空变量:

fun main() {
    var name: String = "Any"    // 非空变量
    var phone: String? = null   // 可空变量
    if (phone != null) {
        print(phone.length)
    } else {
        phone = "12345678901"
        print("phone = " + phone)
   }
}

运行结果:

phone = 12345678901

上述代码,定义一个非空变量 name,一个可空变量 phone。这段示例代码对可空变量进行判断,如果 phone 不为空则输出 phone的长度,否则将phone赋值为12345678901并打印输出。

2. 安全调用符(?.)

上一点的示例中,可空变量在使用时需要先通过if…else判断,然后再进行相应的操作,这样使用还是比较繁琐。Kotlin提供了一个安全调用符?.,用于调用可空类型变量中的成员方法或属性,语法格式为“变量?.成员”。其作用是先判断变量是否为null,如果不为null才调用变量的成员方法或者属性。

fun main() {
    var name: String = "Any"
    var phone: String? = null
    var result = phone?.length
    println(result)
}

运行结果:

null

结果可以看出,在使用?.调用可空变量的属性时,若当前变量为空,则程序编译正常运行,且返回一个null值。

3. Elvis操作符(?:)

安全调用符调用可空变量中的成员方法或属性时,如果当前变量为空,则返回一个null值,但有时不想返回一个null值而是指定一个默认值,该如何处理呢?Kotlin中提供了一个Elvis操作符(?:),通过Elvis操作符(?:)可以指定可空变量为null时,调用该变量中的成员方法或属性的返回值,其语法格式为 表达式 ?: 表达式 。若左边表达式非空,则返回左边表达式的值,否则返回右边表达式的值。

fun main() {
    var name: String = "Any"
    var phone: String? = null
    var result = phone?.length ?: "12345678901"
    println(result)
}

运行结果:

12345678901

从结果可以看出,当变量phone为空时,使用?:操作符会返回指定的默认值“12345678901”,而非null值。

4. 非空断言(!!.)

除了使用安全调用符(?.)来使用可空类型的变量之外,还可以通过非空断言(!!.)来调用可空类型变量的成员方法或属性。使用非空断言时,调用变量成员方法或属性的语法结构为 “变量!!.成员” 。非空断言(!!.)会将任何变量(可空类型变量或者非空类型变量)转换为非空类型的变量,若该变量为空则抛出异常。接下来我们通过一个例子来演示非空断言(!!.)的使用,具体代码如下所示。

fun main() {
    var phone: String? = null    // 声明可空类型变量
    var result = phone!!.length  // 使用非空断言
    println(result)
}

运行结果:

Exception in thread"main"kotlin.KotlinNullPointerException
at NoEmptyAssertionKt.main
(NoEmptyAssertion.kt:4

运行结果抛出了空指针异常,若变量phone赋值不为空,则程序可以正常运行。
安全调用符与非空断言运算符都可以调用可空变量的方法,但是在使用时有一定的差别,如表所示。

操作符安全是否推荐
安全调用符(?.)当变量值为null时,不会抛出异常,更安全推荐使用
非空断言(!!)当变量值为null时,会抛出异常,不安全可空类型变量经过非空断言后,这个变量变为非空变量,非空变量为null时,会报异常,不推荐

总结

上面四种情况的介绍,可以说的很全面地囊括 kotlin 中的空处理情况,开发中应根据实际场景使用合适的操作符。

掘金(JUEJIN)一起进步,一起成长!