五、类型检查和空安全

正如第 1 章 【安卓开发设置】所述,Kotlin 带来的一大特色就是零安全。在这一章中,我们将了解是什么使 Kotlin 成为一种空安全语言,以及我们如何充分利用它。

到本章结束时,我们将了解到:

  • 不可空和可空类型
  • 安全呼叫接线员
  • 猫王接线员
  • !!操作员
  • 安全和不安全的演职人员

零安全

开发人员在 Java 和许多其他语言中最常见的痛点之一就是访问空引用的成员。在大多数语言中,这会导致运行时出现空引用异常。大多数 Java 开发人员都知道这是NullPointerException

Kotlin 旨在尽可能消除遇到空引用、异常的可能性。正如第 1 章安卓开发设置所述,你在 Kotlin 遇到NullPointerException只有四个可能的原因:

  • 一个外部 Java 代码
  • 明确要求抛出NullPointerException
  • !!运算符的用法(我们将在后面详细了解该运算符)
  • 关于初始化的数据不一致

那么 Kotlin 是如何确保这一点的呢?

可空和不可空类型

可空类型是允许保存null值的引用,而不可空类型是不能保存null值的引用。

Kotlin 的类型系统旨在区分这两种类型的引用。可空类型通过在类型末尾附加一个?来声明。例如:

var name: String = "Anna" // non-nullable String
var gender: String? = "Female" //nullable String

name = null // will not compile
gender = null // will compile

print("Length of name is ${name.length}") // will compile

print("Length of gender is ${gender.length}") // will not compile

在前面的代码中,有许多事情需要注意:

  • name不能被赋予null值,因为它是不可空的类型
  • 另一方面,gender可以被赋予一个null值,因为它被声明为可空类型
  • 访问gender的成员方法或属性的方式不能与访问其中一个name成员方法或属性的方式相同

有许多方法可以访问可空类型的方法或属性。您可以检查null并访问条件中的方法或属性。例如:

if (gender != null) {
    print("Length of gender is ${gender.length}") 
}

编译器跟踪null检查的结果,因此允许使用if条件的主体调用length。这是一个智能施法的例子:

  • 使用安全呼叫操作员(?.)
  • 使用猫王操作符(?:)
  • 使用!!操作符
  • 表演聪明的演员阵容

Smart cast is a smart feature in Kotlin where the compiler tracks the results in an if statement and performs casts automatically when needed. 

安全呼叫接线员

访问可空类型的方法或属性的另一种方式是使用安全调用运算符:

val len = gender?.length
print("Length of gender is $len")

在前面的代码中,如果性别不是null,则len的值将是gender.length的结果。否则len的值将是null

gendernull时,如果不需要执行任何操作,使用安全呼叫操作员是很棒的。当gendernull的时候,如果我们想给len分配一个不同的值呢?为此,我们可以将安全呼叫操作员与猫王操作员结合起来。

猫王接线员

猫王运算符类似于 Java 中的三元if运算符。这是简化if-else语句的一种方式。例如:

val len = if (gender != null) gender.length else 0

代码可以简化为:

val len = gender?.length ?: 0

在之前的代码中,gender?.length评估为nulllen的值为0

那个!!操作员

如果我们不关心遇到空指针异常怎么办?然后我们可以利用!!运算符。例如:

val len = gender!!.length

如果gendernull,这将导致空指针异常。

Only use the !! operator if you're either certain of the value of the variable or you don't care about running into a null pointer exception.

类型检查

就像在 Java 中一样,您可以确认变量的类型。在 Kotlin 中,这是使用is运算符完成的。例如:

if (gender is String) {
    println("Length of gender is ${gender.length}") // gender is automatically cast to a String
}

就像之前的null检查一样,编译器跟踪类型检查的结果,并自动将gender转换为String,因此允许调用gender.length。这叫做聪明的演员阵容。

演职人员

要将变量转换为另一种类型,必须使用转换运算符(as):

var fullname: String = name as String

如果您试图强制转换的变量不是您试图强制转换的类型,强制转换运算符将引发错误。为了防止这种情况,您可以使用安全演职人员 ( as?):

var gen: String? = gender as? String

安全强制转换操作符不会抛出错误,但如果强制转换不可能,则会返回null

摘要

在本章中,我们了解了 Kotlin 帮助您的代码实现空值安全的不同方法。Kotlin 中使用了不同的运算符来实现这一点,我们介绍了如何使用它们。

在下一章中,我们将完成 TicTacToe 游戏的工作,同时学习 Kotlin 中的函数和 lambdas。