list 如何在 Kotlin 中将类型擦除列表转换为数组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41312629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 08:12:28  来源:igfitidea点击:

How to convert a type-erased list to an array in Kotlin?

arrayslistkotlin

提问by mmorihiro

A function toArrayshould convert type-erased list to Tthat is Array<String>now.

函数toArray应该将类型擦除列表转换TArray<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")

However, toArraythrows this error.

但是,toArray抛出此错误。

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

java.lang.ClassCastException: [Ljava.lang.Object; 不能转换为 [Ljava.lang.String;

Do you have any ideas?

你有什么想法?

回答by Ruslan

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.

问题就在这里,是,你实际上是试图投Object[]String[]Java中的条款,或者Array<Any>Array<String>在科特林方面,但这是不同的对象。

So, this statement:

所以,这个声明:

list.toTypedArray()

returns Array<Any?>, and then you trying to cast it to Array<String>and get ClassCastException.

返回Array<Any?>,然后您尝试将其转换为Array<String>并获取ClassCastException.

How to fix?

怎么修?

I suggest pass type parameter itself, and cast List:

我建议传递类型参数本身,并强制转换List

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

toArray<String>(listOf("1", "2"))

回答by mfulton26

To understand why this happens I recommend reading Difference between List and Array types in Kotlinand Java Practices -> Prefer Collections over older classes.

要了解为什么会发生这种情况,我建议阅读KotlinJava 实践中列表和数组类型之间的差异-> 首选集合而不是旧类

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:

一般来说,我建议使用列表而不是数组,但如果您想在 Kotlin 中将类型擦除列表转换为数组,最简单的方法是首先映射到类型列表,然后转换为类型数组:

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:

然后,您可以有效地将 a 转换List<*>为类型化数组:

list.mapToTypedArray { it as String }

回答by epool

For some reason, I was getting an invalid argument number exception when I was trying to do this:

出于某种原因,当我尝试这样做时,我收到了一个无效的参数编号异常:

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

And I ended up doing it this way:

我最终这样做了:

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

Then I was able to destruct my arraywith *arrayfor passing it as a varargsparameter.

然后我能够破坏我的arraywith*array以将其作为varargs参数传递。