我目前正在学习Kotlin以在我的Android应用程序中替换Java,但我正在努力解决null安全问题。
我熟悉处理null和非null变量的过程,但是,我仍然不确定"最佳实践"就Kotlin中的null /非null变量实现而言。
例如,在Java中我会写一些类似的东西:
UserAccount account;
if (account == null) {
openLogin();
}
我知道我可以在Kotlin中复制这个,但似乎该语言旨在避免像这样的练习。如果我要添加一个可以为空的变量,我将如何通过Kotlin实现这个系统呢?
答案 0 :(得分:5)
我知道我可以在Kotlin中复制这个内容,但似乎该语言旨在避免像这样的练习。
请注意语言 without nulls 和 null-safe 语言之间的区别。 Kotlin是后者,这意味着它欢迎并接受null
值,但是,与Java这样的语言相反,它会带来一条带。
Kotlin为您提供了以简洁,可读和安全的方式处理可空类型的语法。对于你的例子,
if (account == null){
openLogin();
}
你可以用这个成语:
account ?: openLogin()
在其他时刻,您会想要对非空account
采取行动,或者只是跳过代码的null
部分。然后你可以使用可选的derefence ?.
:
account?.userName?.also { println("Username is $it") }
答案 1 :(得分: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()非常相似,但在a里面 函数体,run()方法对此引用进行操作而不是 函数参数:
var res = listOf<String?>()
for (item in names) {
item?.run{res = res.plus(this)}
}
答案 2 :(得分: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()
}