Kotlin无效安全的最佳实践

问题描述 投票:2回答:3

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

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

例如,在Java中,我会写一些类似于:

UserAccount account;

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

我知道我可以在Kotlin中复制这个,但似乎语言的设计是为了避免像这样的练习。如果我要添加一个可以为空的变量,我将如何通过Kotlin实现此系统?

kotlin kotlin-null-safety
3个回答
5
投票

我知道我可以在Kotlin中复制这个,但似乎语言的设计是为了避免像这样的练习。

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

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

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

你可以用这个成语:

account ?: openLogin()

在其他时刻,你会想要对非空的account采取行动,或者只是跳过代码的那部分,如果它是null。然后你可以使用可选的derefence ?.

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

4
投票

可能这种材料很有用: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)}
}

2
投票

我知道我可以在Kotlin中复制这个,但似乎语言的设计是为了避免像这样的练习。

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

val account: UserAccount? = ...

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

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

如果我要添加一个可以为空的变量,我将如何通过Kotlin实现此系统?

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

虽然对于这种特殊情况,根据您的要求使用lateinit可能更好:

lateinit var account: UserAccount

...
if (!::account.isInitialized) {
    openLogin()
}
© www.soinside.com 2019 - 2024. All rights reserved.