I am encountering an issue with Kotlin's type system. I declared the variable as below at class scope:
var planets: ArrayList<Planet>? = null
and in the constructor I try to initialize the array but I am encountering a type mismatch error:
planets = arrayListOf(earth, mars, saturn, jupiter, uranus, neptune, pluto)
error:
Required: ArrayList<Planet>?
Found: ArrayList<Planet?>
Why am I getting this error and how do I fix it?
At least one of the planets (earth, mars, saturn, jupiter, uranus, neptune, pluto
) is of nullable type Planet?
hence the inferred type of arrayListOf(earth, ...)
is ArrayList<Planet?>
.
Since ArrayList<Planet>
is not contravariant on type Planet
it cannot be safely to assigned with value ArrayList<Planet?>
.
To resolve the problem you can:
- make sure all planets are of not nullable type
Planet
if the above is not feasible change
var planets: ArrayList<Planet>? = null
to
var planets = arrayListOf<Planet?>()
filter out null
planets and then assign the result collections to planets
:
planets = arrayListOf(*arrayListOf(earth, ...).filterNotNull().toTypedArray())
Another way to make the compiler happy is to make the planets
contravariant like so:
var planets: ArrayList<in Planet>? = null
PS. Use kotlin collection types List<T>
, Set<T>
and corresponding listOf
, setOf
instead of Java's counterparts whenever possible.
Your planets in the list have type Planet?
, not Planet
. Please, check it out.
To fix there are three ways:
1. Change planets type to Planet
.
2. Change list definition to
var planets: ArrayList<Planet?>? = null
3. Map existed planets if you sure they are not null
planets = ArrayList(listOf(earth, ... ).map { it!! })
// or safer way
planets = ArrayList(listOf(earth, ... ).filterNotNull())
Number 2 is the worst one, I prefer number 1, if it is impossible, number 3 as workaround.