Kotlin 中空安全的最佳实践

Best practice for null safety in Kotlin

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

我已经熟悉了处理空变量和非空变量的过程,但是,在 Kotlin 中实现 null/non-null 变量方面,我仍然不确定 "best practice"。

例如,在 Java 中我会这样写:

UserAccount account;

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

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

这个 material 可能有用:http://www.baeldung.com/kotlin-null-safety

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

The let() method

To execute an action only when a reference holds a non-nullable value, we can use a let operator.

Let’s say that we have a list of values and there is also a null value in that list:

val firstName = "Tom"
val secondName = "Michael" val names:
List<String?> = listOf(firstName, null, secondName)

Next, we can execute an action on every non-nullable element of the names list by using a let function:

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

The run() method

Kotlin has a run() method to execute some operation on a nullable reference. It is very similar to let() but inside of a function body, the run() method operates on this reference instead of a function parameter:

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

I understand I can replicate this in Kotlin but it seems as though the language is designed to avoid practice like this.

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

Kotlin 为您提供了以简洁、可读和安全的方式处理可空类型的语法。例如,

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

你可以使用这个成语:

account ?: openLogin()

在其他时候,您可能想要对非空值 account 执行操作,或者如果它是 null 则跳过该部分代码。然后你可以使用可选的取消引用 ?.:

account?.userName?.also { println("Username is $it") }

I understand I can replicate this in Kotlin but it seems as though the language is designed to avoid practice like this.

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

val account: UserAccount? = ...

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

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

How would I go about implementing this system through Kotlin, should I be adding a nullable variable?

您没有添加 变量,您指定account 在其类型中可以为空。

尽管对于这种特定情况,使用 lateinit 可能更好,具体取决于您的要求:

lateinit var account: UserAccount

...
if (!::account.isInitialized) {
    openLogin()
}