web-dev-qa-db-fra.com

Comment convertir une liste de types effacés en un tableau dans Kotlin?

Une fonction toArray devrait convertir la liste de types effacés en T qui correspond maintenant à Array<String>.

inline fun <reified T> toArray(list: List<*>): T {
    return list.toTypedArray() as T
}

toArray<Array<String>>(listOf("a", "b", "c")) // should be arrayOf("a", "b", "c")

Cependant, toArray lève cette erreur.

Java.lang.ClassCastException: [Ljava.lang.Object; ne peut pas être converti en [Ljava.lang.String;

Avez-vous des idées?

14
mmorihiro

Le problème ici est que vous essayez réellement de transtyper Object[] en String[] en termes de Java, ou de Array<Any> en Array<String> en termes de Kotlin, mais il s'agit d'objets différents.

Donc, cette déclaration:

list.toTypedArray()

renvoie Array<Any?> et vous essayez ensuite de le transtyper en Array<String> et obtenez ClassCastException

Comment réparer?

Je suggère de passer le paramètre de type lui-même et de transtyper List:

inline fun <reified T> toArray(list: List<*>): Array<T> {
    return (list as List<T>).toTypedArray()
}

toArray<String>(listOf("1", "2"))
34
IRus
  1. Je vous recommande de contester votre besoin de convertir un List<*> en un tableau typé (par exemple Array<String>) au lieu d'une liste typée (par exemple List<String>).

    Ce dernier peut être très bien fait à Kotlin:

    list.map { it as String }
    

    Je recommande de lire Différence entre les types List et Array dans Kotlin et Pratiques Java -> Préférer les collections aux anciennes classes .

  2. Si vous pensez toujours que vous devez travailler avec des tableaux, je vous recommande de créer une fonction "map" similaire aux différentes fonctions "map" de Kotlin:

    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()) } }
        }
    }
    

    Vous pouvez ensuite convertir efficacement un List<*> en un tableau typé:

    list.mapToTypedArray { it as String }
    
3
mfulton26

Pour une raison quelconque, je recevais une exception de numéro d'argument non valide lorsque j'essayais de le faire:

val argumentTypeMirrors = mutableListOf<TypeMirror>()
... // add items to argumentTypeMirrors
val array = argumentTypeMirrors.toTypedArray()

Et j'ai fini par le faire de cette façon:

val argumentTypeMirrors = mutableListOf<TypeMirror>()
... // add items to argumentTypeMirrors
val array = Array(argumentTypeMirrors.size) {
    argumentTypeMirrors[it]
}

Ensuite, j'ai pu détruire ma array avec *array pour la transmettre en tant que paramètre varargs.

0
epool