Kotlin 空值安全综合指南

1. 概述
在本文中,我们将研究 Kotlin 语言中内置的 null 安全功能。Kotlin 提供了对可空字段的全面、原生处理——不需要额外的库。

2. Maven 依赖
首先,您需要将kotlin-stdlib Maven 依赖项添加到pom.xml:

<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib</artifactId>
    <version>1.1.1</version>
</dependency>
您可以在Maven Central上找到最新版本。

3. 可为空和不可为空的引用类型
Kotlin 有两种类型的引用,它们由编译器解释,以便在编译时向程序员提供有关程序正确性的信息——一种是可以为空的,另一种是不可为空的。

默认情况下,Kotlin 假定 value 不能为null:

var a: String = "value"

assertEquals(a.length, 5)
我们不能为引用a分配null,如果您尝试这样做,它将导致编译器错误。

如果我们想创建一个可为空的引用,我们需要创建附加问号(?)到类型定义:

var b: String? = "value"
之后,我们可以给它赋值null:

b = null
当我们想要访问b引用时,我们必须显式处理null情况以避免编译错误,因为 Kotlin 知道这个变量可以保存null:

if (b != null) {
    println(b.length)
} else {
    assertNull(b)
}
4. 安全通话
以这种方式处理每个可为空的引用可能很麻烦。幸运的是,Kotlin 有一个“安全调用”语法——这种语法允许程序员仅在特定引用持有非空值时才执行操作。

让我们定义两个数据类来说明这个特性:

data class Person(val country: Country?)

data class Country(val code: String?)
请注意,国家/地区和代码字段是可为空引用类型。

要以流畅的方式访问这些字段,我们可以使用安全调用语法:

val p: Person? = Person(Country("ENG"))

val res = p?.country?.code

assertEquals(res, "ENG")
如果变量p持有一个null,安全调用语法将返回一个null结果:

val p: Person? = Person(Country(null))

val res = p?.country?.code

assertNull(res)
4.1. let() 方法
要仅在引用持有不可为空的值时执行操作,我们可以使用let运算符。

假设我们有一个值列表,并且该列表中还有一个空值:

val firstName = "Tom"
val secondName = "Michael"
val names: List<String?> = listOf(firstName, null, secondName)
接下来,我们可以使用let函数对名称列表的每个不可为空的元素执行一个操作:

var res = listOf<String?>()
for (item in names) {
    item?.let { res = res.plus(it) }
}

assertEquals(2, res.size)
assertTrue { res.contains(firstName) }
assertTrue { res.contains(secondName) }
4.2. also() 方法
如果我们想应用一些额外的操作,例如记录每个不可为空的值,我们可以使用also() 方法并将它与let() 链接起来:

var res = listOf<String?>()
for (item in names) {
    item?.let { res = res.plus(it); it }
  ?.also{it -> println("non nullable value: $it")}
}
它将打印出每个不为空的元素:

non nullable value: Tom
non nullable value: Michael
4.3. run() 方法
Kotlin 有一个run()方法来对可空引用执行一些操作。它与let()非常相似,但在函数体内部, Run() 方法 对这个引用而不是函数参数进行操作:

var res = listOf<String?>()
for (item in names) {
    item?.run{res = res.plus(this)}
}
5. 猫王接线员
有时,当我们有一个引用时,如果引用为null,我们希望从操作中返回一些默认值。为此,我们可以使用elvis ( ?: ) 运算符。这相当于Java Optional类中的orElse/orElseGet:

val value: String? = null

val res = value?.length ?: -1

assertEquals(res, -1)
当值引用持有不可为空的值时,将调用方法length:

val value: String? = "name"

val res = value?.length ?: -1

assertEquals(res, 4)
6. Nullable Unsafe Get
Kotlin 也有一个不安全的运算符来获取可空字段的值,而无需显式处理缺席逻辑,但应该非常小心地使用它。

双感叹号运算符 ( !! ) 从可空引用中获取一个值,如果它为null,则抛出NullPointerException 。这相当于Optional.get()操作:

var b: String? = "value"
b = null

assertFailsWith<NullPointerException> {
    b!!
}
如果可空引用持有不可空值,则对该值的操作将成功执行:

val b: String? = "value"

assertEquals(b!!.length, 5)
7. 从列表中过滤空值
Kotlin 中的List类有一个实用方法filterNotNull(),它仅从包含可空引用的列表中返回不可为空的值:

val list: List<String?> = listOf("a", null, "b")

val res = list.filterNotNull()

assertEquals(res.size, 2)
assertTrue { res.contains("a") }
assertTrue { res.contains("b") }
这是一个非常有用的构造,它封装了我们需要自己实现的逻辑。

8. 结论
在本文中,我们深入探讨了 Koltin 的零安全功能。我们看到了可以保存空值和不能保存空值的引用类型。我们通过使用“安全调用”功能和elvis运算符实现了流畅的空处理逻辑。

所有这些示例和代码片段的实现都可以在GitHub 项目中找到——这是一个 Maven 项目,所以它应该很容易导入和运行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值