如何将nullable类型传递给采用非null类型的函数?

时间:2015-04-23 18:39:53

标签: kotlin

如果我在通过前进行空检查,这可能吗?例如:

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

我不明白为什么编译器不允许我传递可空的内容,即使我先检查它是否为空。谁能解释一下?

4 个答案:

答案 0 :(得分:5)

注意:从编译器版本1.0 beta开始,有问题的代码按原样工作

编译器可以判断变量是否在检查和使用之间发生变异,至少在此问题中的局部变量的情况下,以及在其他一些情况下。有关详细信息,请参阅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或更新版本)中,您不再有此问题。你的代码会编译。 valvar的局部变量可以安全地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()
}

了解详情:Checking for null in conditions

答案 2 :(得分:1)

您可以使用isinstance来简化代码。 kotlin范围函数在“ num”的上下文中引入了局部变量。无需声明临时变量{'2019-02-03': {}}

let

与下面的工作方式相同,但更简单,更干净。

numVal

答案 3 :(得分:0)

使用可以与空安全运算符?一起使用作用域函数let或应用。

 fragmentManager?.let{
        viewPager.adapter = TasksPagerAdapter(it)
    }

通过这种方式,您可以将可为空的类型传递给不可为空的类型参数