2

我目前正在学习 Kotlin 以在我的 android 应用程序中替换 Java,但正在努力解决 null 安全问题。

我正在熟悉处理空变量和非空变量的过程,但是,我仍然不确定在 Kotlin 中实现空/非空变量的“最佳实践”。

例如,在 Java 中,我会写如下内容:

UserAccount account;

if (account == null) {
    openLogin();
}

我知道我可以在 Kotlin 中复制这一点,但似乎该语言旨在避免这样的实践。我将如何通过 Kotlin 实现这个系统,我应该添加一个可为空的变量吗?

4

3 回答 3

5

我知道我可以在 Kotlin 中复制这一点,但似乎该语言旨在避免这样的实践。

请注意没有空值的语言和空值安全语言之间的区别。Kotlin 是后者,这意味着它欢迎并接受这种null价值,但与 Java 这样的语言相反,它受到了约束。

Kotlin 提供语法以简洁、易读和安全的方式处理可空类型。对于你的例子,

if (account == null){
    openLogin();
}

你可以使用这个成语:

account ?: openLogin()

在其他时候,您可能想要对非 null 采取行动,account或者如果它是null. 然后你可以使用可选的 derefence ?.

account?.userName?.also { println("Username is $it") }
于 2018-06-05T06:09:55.040 回答
5

这种材料可能有用:http ://www.baeldung.com/kotlin-null-safety

您可以搜索 let() 和 run() 方法。

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) }

run() 方法

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

var res = listOf<String?>()
for (item in names) {
    item?.run{res = res.plus(this)}
}
于 2018-06-05T03:17:53.590 回答
2

我知道我可以在 Kotlin 中复制这一点,但似乎该语言旨在避免这样的实践。

我会说正好相反,它旨在支持它。例如,如果你有

val account: UserAccount? = ...

if (account == null){
    openLogin()
} else {
    ...
}

编译器知道account它不在分支中,并且它可以null在那里else有效地具有不可为空的UserAccount类型。(小警告:在您的情况下account更可能是 a var,这对智能转换施加了一些限制。)

我将如何通过 Kotlin 实现这个系统,我应该添加一个可为空的变量吗?

您不添加变量,而是指定account其类型可以为空。

尽管对于这种特定情况lateinit,根据您的要求,使用 可能会更好:

lateinit var account: UserAccount

...
if (!::account.isInitialized) {
    openLogin()
}
于 2018-06-05T06:34:29.470 回答