Nat*_*han 34 java arrays generics reification kotlin
我有一个包含T和一些元数据的数组(或列表)的接口.
interface DataWithMetadata<T> {
val someMetadata: Int
fun getData(): Array<T>
}
Run Code Online (Sandbox Code Playgroud)
如果我编写最简单的接口实现,我会得到一个编译错误emptyArray()
:"不能使用T作为一个改进的类型参数.请改用类."
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
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我将接口和实现都更改为列表,我没有编译时问题:
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
}
}
Run Code Online (Sandbox Code Playgroud)
我怀疑在我的问题中Kotlin泛型有一些有趣的教训.任何人都可以告诉我编译器在幕后做了什么以及为什么Array失败但List没有?是否有一种惯用的方法可以在此上下文中编译Array实现?
奖金问题:我达到Array over List的唯一原因是我经常看到Kotlin开发人员喜欢Arrays.是这种情况,如果是这样,为什么?
msr*_*rd0 24
看一下emptyArray()
kotlin stdlib(jvm)中的声明,我们注意到了reified
type参数:
public inline fun <reified @PureReifiable T> emptyArray(): Array<T>
Run Code Online (Sandbox Code Playgroud)
该reified
类型参数意味着你可以访问类T
在编译时,可以像访问它T::class
.您可以reified
在Kotlin参考中阅读有关类型参数的更多信息.由于Array<T>
编译为java T[]
,我们需要在编译时知道类型,因此reified
参数.如果您尝试编写没有reified
关键字的emptyArray()函数,您将收到编译器错误:
fun <T> emptyArray() : Array<T> = Array(0, { throw Exception() })
Run Code Online (Sandbox Code Playgroud)
不能使用T作为reified类型参数.请改用一个班级.
现在,我们来看看实现emptyList()
:
public fun <T> emptyList(): List<T> = EmptyList
Run Code Online (Sandbox Code Playgroud)
该实现根本不需要参数T
.它只返回内部对象EmptyList
,它本身继承自内部对象List<Nothing>
.kotlin类型Nothing
是throw
关键字的返回类型,是一个从不存在的值(引用).如果方法返回Nothing
,则相当于在该位置抛出异常.所以我们可以安全地Nothing
在这里使用,因为每次我们调用EmptyList.get()
编译器都会知道这会返回异常.
奖金问题:
来自Java和C++,我习惯ArrayList
或者std::vector
更容易使用那些数组.我现在使用kotlin几个月,在编写源代码时,我通常看不到数组和列表之间的巨大差异.两者都有大量有用的扩展函数,它们以类似的方式运行.但是,Kotlin编译器处理的数组和列表非常不同,因为Java互操作性对于Kotlin团队非常重要.我通常更喜欢使用列表,这也是我在你的情况下推荐的.
问题是Array
必须在编译时知道an的泛型类型,这由reified
类型参数在此处指示,如声明中所示:
public inline fun <reified @PureReifiable T> emptyArray(): Array<T>
Run Code Online (Sandbox Code Playgroud)
只能创建类似于Array<String>
或Array<Int>
不是类型的具体数组Array<T>
.
在这个答案中,您可以找到几种解决方法.希望你找到合适的方式.
归档时间: |
|
查看次数: |
14012 次 |
最近记录: |