Kotlin类型推断失败 – 类型不匹配“Found Array <*?>,必需数组<*>?”

我遇到了Kotlin类型系统的问题。 我在类的范围内声明了如下的变量:

var planets: ArrayList<Planet>? = null 

并在构造函数中尝试初始化数组,但遇到类型不匹配错误:

 planets = arrayListOf(earth, mars, saturn, jupiter, uranus, neptune, pluto) 

错误:

 Required: ArrayList<Planet>? Found: ArrayList<Planet?> 

为什么我得到这个错误,我该如何解决?

至少有一个行星( earth, mars, saturn, jupiter, uranus, neptune, pluto )是可以为空的Planet? 因此arrayListOf(earth, ...)的推断类型是ArrayList<Planet?>

由于ArrayList<Planet>在类型Planet上不是逆变,所以不能安全地赋值为ArrayList<Planet?>

要解决这个问题,你可以:

  • 确保所有的行星都是不可空Planet
  • 如果以上是不可行的改变

     var planets: ArrayList<Planet>? = null 

     var planets = arrayListOf<Planet?>() 
  • 滤除null行星,然后将结果集合分配给planets

     planets = arrayListOf(*arrayListOf(earth, ...).filterNotNull().toTypedArray()) 

让编译器感到高兴的另一种方式是使planets 逆转如此:

 var planets: ArrayList<in Planet>? = null 

PS。 尽可能使用kotlin集合类型 List<T>Set<T>和相应的listOfsetOf而不是Java的对应。

列表中的Planet?Planet? ,而不是Planet 。 请检查一下。

修复有三种方法:
1.将行星类型更改为Planet
2.将列表定义更改为

 var planets: ArrayList<Planet?>? = null 

3.如果你确定它们不是null,则映射存在的行星

 planets = ArrayList(listOf(earth, ... ).map { it!! }) // or safer way planets = ArrayList(listOf(earth, ... ).filterNotNull()) 

数字2是最差的,我更喜欢数字1,如果不可能,数字3是解决方法。