空值安全
在 Kotlin 中, null
值是有可能出现的。当某些东西缺失或尚未设置时,Kotlin 就会使用 null
值。 你已经在 集合 章节中看到过 Kotlin 返回 null
值的例子,当你尝试访问一个在映射中不存在的键值对时。 虽然以这种方式使用 null
值很有用,但如果你的代码没有准备好处理这些值,你可能会遇到问题。
为了帮助防止程序中出现 null
值问题,Kotlin 提供了 null
安全性。 null
安全性在编译时检测潜在的 null
值问题,而不是在运行时。
null
安全性是一组功能的组合,它允许你:
可空类型
Kotlin 支持可空类型,这允许声明的类型具有 null
值。 默认情况下,类型 不 允许接受 null
值。可空类型通过在类型声明后显式添加 ?
来声明。
例如:
fun main() {
// neverNull 具有 String 类型
var neverNull: String = "This can't be null"
// 会抛出编译错误
neverNull = null
// nullable 具有可空 String 类型
var nullable: String? = "You can keep a null here"
// 这没问题
nullable = null
// 默认情况下,null 值是不被接受的
var inferredNonNull = "The compiler assumes non-nullable"
// 会抛出编译错误
inferredNonNull = null
// notNull 不接受 null 值
fun strLength(notNull: String): Int {
return notNull.length
}
println(strLength(neverNull)) // 18
println(strLength(nullable)) // 会抛出编译错误
}
检查 null
值
你可以在条件表达式中检查 null
值的存在。在下面的例子中, describeString()
函数有一个 if
语句,它检查 maybeString
是否 不 为 null
并且其 length
是否大于零:
fun describeString(maybeString: String?): String {
if (maybeString != null && maybeString.length > 0) {
return "String of length ${maybeString.length}"
} else {
return "Empty or null string"
}
}
fun main() {
val nullString: String? = null
println(describeString(nullString))
// Empty or null string
}
使用安全调用
要安全地访问可能包含 null
值的对象的属性,可以使用安全调用操作符 ?.
。 安全调用操作符会在对象或其访问的属性为 null
时返回 null
。 这在你想避免 null
值在代码中触发错误时非常有用。
在下面的例子中, lengthString()
函数使用安全调用来返回字符串的长度或 null
:
fun lengthString(maybeString: String?): Int? = maybeString?.length
fun main() {
val nullString: String? = null
println(lengthString(nullString))
// null
}
安全调用操作符也可以用来安全地调用扩展函数或成员函数。 在这种情况下,会在调用函数之前执行 null
检查。如果检查发现 null
值,则跳过调用并返回 null
。
在下面的例子中, nullString
为 null
,因此调用 .uppercase()
被跳过,返回 null
:
fun main() {
val nullString: String? = null
println(nullString?.uppercase())
// null
}
使用 Elvis 操作符
你可以使用 Elvis 操作符 ?:
提供一个默认值,当检测到 null
值时返回该默认值。
在 Elvis 操作符的左侧写出要检查的 null
值,在右侧写出检测到 null
值时应返回的默认值。
在下面的例子中, nullString
为 null
,因此安全调用访问 length
属性返回 null
值。 结果,Elvis 操作符返回 0
:
fun main() {
val nullString: String? = null
println(nullString?.length ?: 0)
// 0
}
有关 Kotlin 中 null
安全性的更多信息,请参见 空值安全。
实践
练习
你有一个 employeeById
函数,它可以访问公司员工的数据库。 不幸的是,这个函数返回 Employee?
类型的值,因此结果可能是 null
。 你的目标是编写一个函数,当提供员工的 id
时返回该员工的薪水,如果数据库中缺少该员工,则返回 0
。
data class Employee (val name: String, var salary: Int)
fun employeeById(id: Int) = when(id) {
1 -> Employee("Mary", 20)
2 -> null
3 -> Employee("John", 21)
4 -> Employee("Ann", 23)
else -> null
}
fun salaryById(id: Int) = // 在这里写下你的代码
fun main() {
println((1..5).sumOf { id -> salaryById(id) })
}
data class Employee (val name: String, var salary: Int)
fun employeeById(id: Int) = when(id) {
1 -> Employee("Mary", 20)
2 -> null
3 -> Employee("John", 21)
4 -> Employee("Ann", 23)
else -> null
}
fun salaryById(id: Int) = employeeById(id)?.salary ?: 0
fun main() {
println((1..5).sumOf { id -> salaryById(id) })
}
下一步是什么?
恭喜!现在你已经完成了 Kotlin 之旅,之后请查看我们有关 Kotlin 常用应用的教程:
Last modified: 26 十一月 2024