如何调用具有类的泛型类型的lambda字段?出于某种原因,对Example<*>
这样的通用类的引用会产生一个接受,用Example<Something>
替换原始类型(如Nothing
)。如何仅通过引用Example<*>
?
Codebase我遇到了这个问题:https://github.com/Jire/Acelta/tree/master/src/main/kotlin/com/acelta/packet/incoming/packets
我正在尝试使用此代码,但正如您在第5行所看到的,我无法调用lambda,因为接受类型为Nothing
。
private val incoming = arrayOfNulls<Packet<*>>(256)
fun incoming(id: Int, packeteer: Packeteer) {
val packet = incoming[id] ?: return
packet.receive(packeteer, /* this is type Nothing! */)
}
答案 0 :(得分:2)
此行为正是star projections(Foo<*>
)在Kotlin中的作用。
正如文档中所述
对于
Foo<T>
,其中T
是带上部的不变类型参数 绑定TUpper
,Foo<*>
相当于Foo<out TUpper>
进行阅读 值和Foo<in Nothing>
用于写入值。
如果你使用星形投影Packet<*>
,你对它的泛型类型一无所知,因此你不能安全地将任何值传递给期望泛型参数的方法(这就是Nothing
类型存在的原因)
您可以使用in-projection为通用类型指定下限,对于Packet<in SomeType>
,您可以将SomeType
的实例传递到方法。这将要求Packet
的实际类型参数为SomeType
或其某些祖先,类似于Java中的? super T
通配符:
private val incoming = arrayOfNulls<Packet<in SomeType>>(256)
fun incoming(id: Int, packeteer: Packeteer) {
val packet = incoming[id] ?: return
packet.receive(packeteer, someTypeInstance)
}
否则,您可以使用未经检查的强制转换来调用该方法,尽管它可能会导致ClassCastException
被抛出到某处:
(packet as Packet<in SomeType>).receive(packeteer, someTypeInstance)