user6587056
user6587056

Reputation:

How to cast Any to a List in Kotlin?

When I try to cast Any to a List like in the example below I get 'Unchecked cast: Any! to List' warning. Are there any workarounds to this kind of problem?

val x: List<Apples> = objectOfTypeAny as List<Apples>

Upvotes: 14

Views: 20533

Answers (5)

keocra
keocra

Reputation: 633

As an extension function I came to following solution:

fun <X> Any?.mapToTypedList(desiredListElementType: Class<X>): MutableList<X?> {
    if (this == null) throw IllegalStateException("Provided object is null")
    if (this !is List<*>) throw IllegalStateException("Provided object not of type List")
    val castedList: List<*> = this
    if (castedList.any { it != null && !desiredListElementType.isInstance(it) }) throw IllegalStateException("Found element in list which is not of correct type $desiredListElementType")
    return castedList.map { when(it) {
        null -> null
        else -> desiredListElementType.cast(it)
    } }.toMutableList()
}

Usage (x is of any type but actually contains a list of String):

val castedList: MutableList<String?> = x.mapToTypedList(String::class.java)

Upvotes: 0

amiron
amiron

Reputation: 731

1. Add:

    inline fun <reified T> List<*>.asListOfType(): List<T>? =
        if (all { it is T })
            @Suppress("UNCHECKED_CAST")
            this as List<T> else
            null

2. Use:

    val list: List<YouType> = someAnyList?.asListOfType<YouType>() 

Upvotes: 0

Fortran
Fortran

Reputation: 2336

Solution case for android Serializable to ArrayList:

ModJsonAndDb - your class

private fun serializableToArrayList(obj: Serializable?): ArrayList<ModJsonAndDb>? {
    return if (obj is ArrayList<*>) {
        ArrayList(obj.filterIsInstance<ModJsonAndDb>())
    } else {
        null
    }
}

Upvotes: 0

guenhter
guenhter

Reputation: 12167

This is "just" a warning saying that it's not 100% safe just to cast. The better option would be:

if (objectOfTypeAny is List<*>) {
        val a: List<Apples> = objectOfTypeAny.filterIsInstance<Apples>()
        ...
}

See https://kotlinlang.org/docs/reference/typecasts.html for details.

Upvotes: 30

JB Nizet
JB Nizet

Reputation: 691685

Except ignoring the warning (or improving the design to avoid the cast), no.

This warning means that the cast can succeed at runtime even though the list is not actually a List<Apples>, but contains something other than Apples.

It exists because generics are not reified in Java. Generics work with type erasure. they're a compile-time safety net, not a runtime safety net.

Upvotes: 3

Related Questions