Kotlin泛型类型参数不匹配:推断的类型为“非空”,但预期为“可空”

时间:2019-03-01 11:06:10

标签: generics kotlin

我有一个带有参数T的数据包装器类。此类中有function,具有 generic 容器,其类型为nullable:T? (例如LiveData

class Wrapper<T> {
   fun add (data: LiveData<T?>) {
    // ...
   }
}

在这个地方,我确实需要这种类型。 当我尝试使用此方法并传递非null类型的参数时:

class Program {
   fun get() {
      // some generic container, e.g. LiveData
      val data: LiveData<Int> = MutableLiveData()
      val wrapper = Wrapper<Int>()
      wrapper.add(data)
                  ^^^^ error
   }
}

这是“类型不匹配”错误:image link

Type mismatch: inferred type is LiveData<Int> but LiveData<Int?> was expected

如何处理?如何将通用类型参数从非null强制转换为可空值?

2 个答案:

答案 0 :(得分:1)

这是与variance有关的错误:如果将LiveData<Int?>设为LiveData<Int>变量,T只能是out的子类型:

class LiveData<out T>
  

一般规则是:当类T的类型参数C为   声明为“已淘汰”,则只能在C的成员中排名第一,   但作为回报,C<Base>可以安全地成为C<Derived>的超类型。

     

在“聪明的话”中,他们说类C在   参数T,或T是协变类型参数。您可以   认为CT的生产者,而不是   T

但是最好更改add签名以接受LiveData<T>,除非不希望这样做。

答案 1 :(得分:0)

您可以将Wrapper类声明修改为以下内容

class Wrapper<T> {
   fun add (data: LiveData<T>) {
    // ...
   }

我在T?类型参数中将T替换为LiveData。这样您就可以同时拥有Wrapper<Int>Wrapper<Int?>类型。

Kotlin从不可为空的类型(例如,Int?)中告诉可为空的类型(例如Int)。 LiveData。您可以查看该文章以获取更多详细信息: https://kotlinlang.org/docs/reference/null-safety.html

在上一个答案中建议第二个选项使用方差。 #define MACRO_NAME 8192类/接口的某些实现可能无法使用。
https://kotlinlang.org/docs/reference/generics.html