如果我在通过前进行空检查,这可能吗?例如:
fun main(args: Array<String>) {
var num: Int? = null
// Stuff happens that might make num not null
...
if (num != null) doSomething(num)
}
fun doSomething(number: Int) {
...
}
我不明白为什么编译器不允许我传递可空的内容,即使我先检查它是否为空。谁能解释一下?
答案 0 :(得分:5)
编译器可以判断变量是否在检查和使用之间发生变异,至少在此问题中的局部变量的情况下,以及在其他一些情况下。有关详细信息,请参阅Jayson's answer。
http://kotlinlang.org/docs/reference/null-safety.html#checking-for-null-keyword--in-conditions说
编译器跟踪有关[null]检查的信息......这只适用于b是不可变的(即本地val或具有支持字段且不可覆盖的成员val),否则可能会发生b检查后,b变为null。
所以这样的事情应该有效:
fun main(args: Array<String>) {
var num: Int? = null
// Stuff happens that might make num not null
...
val numVal: Int? = num
if (numVal != null) doSomething(numVal)
}
fun doSomething(number: Int) {
...
}
当然,改写更好更好......#34;以这种方式,您可以首先将num
变为val
。
答案 1 :(得分:2)
在目前的Kotlin(1.0 beta或更新版本)中,您不再有此问题。你的代码会编译。 val
或var
的局部变量可以安全地Smart Cast,因为编译器可以确定该值是否可以变异(例如,在另一个线程上)。
以下是another Stack Overflow question的摘录,其中涵盖了可空性的更多方面以及Kotlin的操作员处理它们。
null
检查和智能广播如果使用null
检查保护对可空类型的访问,编译器将smart cast语句正文中的值不可为空。有一些复杂的流程,这是不可能的,但对于常见的情况工作正常。
val possibleXyz: Xyz? = ...
if (possibleXyz != null) {
// allowed to reference members:
possiblyXyz.foo()
// or also assign as non-nullable type:
val surelyXyz: Xyz = possibleXyz
}
或者,如果您执行is
检查非可空类型:
if (possibleXyz is Xyz) {
// allowed to reference members:
possiblyXyz.foo()
}
同样的&#39;当&#39;也是安全演员的表达式:
when (possibleXyz) {
null -> doSomething()
else -> possibleXyz.foo()
}
// or
when (possibleXyz) {
is Xyz -> possibleXyz.foo()
is Alpha -> possibleXyz.dominate()
is Fish -> possibleXyz.swim()
}
有些事情不允许null
检查smart cast以便稍后使用该变量。上面的示例使用的局部变量绝不会在应用程序流中发生变异,无论val
还是var
此变量都没有机会变异为null
。但是,在编译器无法保证流分析的其他情况下,这将是一个错误:
var nullableInt: Int? = ...
public fun foo() {
if (nullableInt != null) {
// Error: "Smart cast to 'kotlin.Int' is impossible, because 'nullableInt' is a mutable property that could have been changed by this time"
val nonNullableInt: Int = nullableInt
}
}
变量nullableInt
的生命周期不完全可见,可能会从其他线程分配,null
检查不能smart cast为非可空值。请参阅&#34;安全通话&#34;以下主题为解决方法。
smart cast无法信任的另一种不变异的情况是具有自定义getter的对象上的val
属性。在这种情况下,编译器无法查看改变值的内容,因此您将收到错误消息:
class MyThing {
val possibleXyz: Xyz?
get() { ... }
}
// now when referencing this class...
val thing = MyThing()
if (thing.possibleXyz != null) {
// error: "Kotlin: Smart cast to 'kotlin.Int' is impossible, because 'p.x' is a property that has open or custom getter"
thing.possiblyXyz.foo()
}
答案 2 :(得分:1)
您可以使用isinstance
来简化代码。 kotlin范围函数在“ num”的上下文中引入了局部变量。无需声明临时变量{'2019-02-03': {}}
。
let
与下面的工作方式相同,但更简单,更干净。
numVal
答案 3 :(得分:0)
使用可以与空安全运算符?一起使用作用域函数let或应用。
fragmentManager?.let{
viewPager.adapter = TasksPagerAdapter(it)
}
通过这种方式,您可以将可为空的类型传递给不可为空的类型参数