如何将可空类型传递给非空类型的函数?

如果我在传球之前进行空检查,这是可能的吗? 例如:

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

我不明白为什么编译器不会让我通过一个空,即使我检查它不是空的第一。 谁能解释一下?

注意:从编译器版本1.0 beta开始,问题代码按原样运行

编译器可以判断变量是否在检查和使用之间发生变化,至少在本地变量(如在这个问题中)以及其他情况下。 详见杰森的回答 。


http://kotlinlang.org/docs/reference/null-safety.html#checking-for-null-keyword–in-conditions&#x8BF4;

编译器追踪有关[null]检查的信息…这只适用于b不可变的地方(即一个本地val或者一个具有支持字段且不可覆盖的成员val),否则可能发生b改变检查后为空。

所以这样的事情应该工作:

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

当然,重写“发生的事情”会更好,这样你可以首先将num写入val

在目前的Kotlin(1.0 beta或更新版本)中,你不再有这个问题了。 你的代码将被编译。 valvar局部变量可以安全地进行智能Cast,因为编译器可以确定该值是否可能已经变异(例如在另一个线程上)。

这里是另一个堆栈溢出问题的摘录,涵盖了可空性的更多方面和Kotlin的操作符处理它们。

有关null检查和智能转换的更多信息

如果使用null检查保护对可空类型的访问,编译器将智能地将语句体内的值转换为非空值。 有一些复杂的流程,这不可能发生,但一般情况下工作正常。

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

对于'when'表达式也是安全的:

 when (possibleXyz) { null -> doSomething() else -> possibleXyz.foo() } // or when (possibleXyz) { is Xyz -> possibleXyz.foo() is Alpha -> possibleXyz.dominate() is Fish -> possibleXyz.swim() } 

有些事情不允许null检查智能强制转换为以后使用的变量。 上面的例子使用了一个本地变量,这个变量在应用程序的流程中决不可能发生变化,无论valvar这个变量是否没有机会变为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检查不能被智能转换为不可空值。 有关解决方法,请参阅下面的“安全调用”主题。

另一个智能强制转换不能被信任的情况是具有自定义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 'px' is a property that has open or custom getter" thing.possiblyXyz.foo() } 

阅读更多: 检查条件为空