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
How to convert a type-erased list to an array in Kotlin?
提问by mmorihiro
A function toArray
should convert type-erased list to T
that is Array<String>
now.
函数toArray
应该将类型擦除列表转换T
为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")
However, toArray
throws 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.
要了解为什么会发生这种情况,我建议阅读Kotlin和Java 实践中列表和数组类型之间的差异-> 首选集合而不是旧类。
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 array
with *array
for passing it as a varargs
parameter.
然后我能够破坏我的array
with*array
以将其作为varargs
参数传递。