How to convert a type-erased list to an array in Kotlin?
To understand why this happens I recommend reading Difference between List and Array types in Kotlin and Java Practices -> Prefer Collections over older classes.
In general I recommend using lists instead of arrays but if you want to convert a type-erased list to an array in Kotlin the easiest way to do so is first mapping to a typed list and then converting to a typed array:
list.map { it as String }.toTypedArray()
If you don't actually need an array but a typed list will do then you can simply map the type-erased list to a typed list:
list.map { it as String }
If you find yourself often converting a type-erased list to an array and performance matters then I recommend creating a map function optimized for doing this while avoiding an intermediary list:
inline fun <T, reified R> List<T>.mapToTypedArray(transform: (T) -> R): Array<R> {
return when (this) {
is RandomAccess -> Array(size) { index -> transform(this[index]) }
else -> with(iterator()) { Array(size) { transform(next()) } }
}
}
You can then efficiently convert a List<*>
to a typed array:
list.mapToTypedArray { it as String }
Problem here, is that you actually trying cast Object[]
to String[]
in terms of Java, or Array<Any>
to Array<String>
in terms of Kotlin, but this is different objects.
So, this statement:
list.toTypedArray()
returns Array<Any?>
, and then you trying to cast it to Array<String>
and get ClassCastException
.
How to fix?
I suggest pass type parameter itself, and cast List
:
inline fun <reified T> toArray(list: List<*>): Array<T> {
return (list as List<T>).toTypedArray()
}
toArray<String>(listOf("1", "2"))