赞
踩
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 项目,所以它应该很容易导入和运行。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。