没有-6ren"> 没有-我有一个接口(interface),其中包含 T 的数组(或列表)和一些元数据。 interface DataWithMetadata { val someMetadata: Int -6ren">
gpt4 book ai didi

java - Kotlin 泛型 Array 结果为 "Cannot use T as a reified type parameter. Use a class instead"但 List 没有

转载 作者:IT老高 更新时间:2023-10-28 13:28:06 28 4
gpt4 key购买 nike

我有一个接口(interface),其中包含 T 的数组(或列表)和一些元数据。

interface DataWithMetadata<T> {
val someMetadata: Int
fun getData(): Array<T>
}

如果我编写接口(interface)的最简单实现,我会在 emptyArray() 上得到一个编译错误:“Cannot use T as a reified type parameter. Use a class instead.”

class ArrayWithMetadata<T>(override val someMetadata: Int): DataWithMetadata<T> {
private var myData: Array<T> = emptyArray()

override fun getData(): Array<T> {
return myData
}

fun addData(moreData: Array<T>) {
this.myData += moreData
}
}

但是,如果我将接口(interface)和实现都更改为列表,则不会出现编译时问题:

interface DataWithMetadata<T> {
val someMetadata: Int
fun getData(): List<T>
}

class ListWithMetadata<T>(override val someMetadata: Int): DataWithMetadata<T> {
private var myData: List<T> = emptyList()

override fun getData(): List<T> {
return myData
}

fun addData(moreData: Array<T>) {
this.myData += moreData
}
}

我怀疑我的问题中有一些关于 Kotlin 泛型的有趣类(class)。谁能告诉我编译器在幕后做了什么以及为什么 Array 失败但 List 没有?有没有一种惯用的方法可以在这种情况下编译 Array 实现?

额外问题:我使用 Array over List 的唯一原因是我经常看到 Kotlin 开发人员偏爱数组。是这样吗,如果是,为什么?

最佳答案

emptyArray()的声明在 kotlin 标准库 (jvm) 中,我们注意到 reified类型参数:

public inline fun <reified @PureReifiable T> emptyArray(): Array<T>

reified类型参数意味着你可以访问 T 的类在编译时,可以像 T::class 一样访问它.您可以阅读有关 reified 的更多信息Kotlin reference 中的类型参数.从 Array<T>编译成 java T[] ,我们需要在编译时知道类型,因此 reified范围。如果您尝试编写没有 reified 的 emptyArray() 函数关键字,你会得到一个编译器错误:

fun <T> emptyArray() : Array<T> = Array(0, { throw Exception() })

Cannot use T as a reified type parameter. Use a class instead.


现在,我们来看看emptyList()的实现:

public fun <T> emptyList(): List<T> = EmptyList

这个实现不需要参数T一点也不。它只返回内部对象 EmptyList ,它本身继承自 List<Nothing> . kotlin 类型 Nothingthrow 的返回类型关键字并且是永远不存在的值 (reference)。如果方法返回 Nothing , 相当于在那个地方抛出异常。所以我们可以放心使用Nothing因为每次我们都会调用 EmptyList.get()编译器知道这会返回异常。


额外问题:

来自Java和C++,我习惯了ArrayListstd::vector更容易使用该数组。我现在使用 kotlin 几个月了,在编写源代码时,我通常看不到数组和列表之间有很大的区别。两者都有大量有用的扩展函数,它们的行为方式相似。然而,Kotlin 编译器处理数组和列表的方式非常不同,因为 Java 互操作性对 Kotlin 团队非常重要。我通常更喜欢使用列表,这也是我在你的情况下推荐的。

关于java - Kotlin 泛型 Array<T> 结果为 "Cannot use T as a reified type parameter. Use a class instead"但 List<T> 没有,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46869353/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com