我目前正在学习Kotlin以在我的Android应用程序中替换Java,但我正在努力解决null安全问题。
我熟悉处理null和非null变量的过程,但是,我仍然不确定Kotlin中实现null / non-null变量的“最佳实践”。
例如,在Java中,我会写一些类似于:
UserAccount account;
if (account == null) {
openLogin();
}
我知道我可以在Kotlin中复制这个,但似乎语言的设计是为了避免像这样的练习。如果我要添加一个可以为空的变量,我将如何通过Kotlin实现此系统?
我知道我可以在Kotlin中复制这个,但似乎语言的设计是为了避免像这样的练习。
请注意没有空值的语言和空安全语言之间的区别。 Kotlin是后者,这意味着它欢迎并接受null
的价值,但是,与Java这样的语言相反,它带来了它的牵制。
Kotlin为您提供了以简洁,可读和安全的方式处理可空类型的语法。以你为例,
if (account == null){
openLogin();
}
你可以用这个成语:
account ?: openLogin()
在其他时刻,你会想要对非空的account
采取行动,或者只是跳过代码的那部分,如果它是null
。然后你可以使用可选的derefence ?.
:
account?.userName?.also { println("Username is $it") }
可能这种材料很有用: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)}
}
我知道我可以在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()
}