Kotlin:我怎样才能调用一个lambda字段,它有一个泛型类?
我怎样才能调用一个lambda字段有一个泛型类的类? 出于某种原因,像Example<*>
这样的泛型类的引用会产生一个用Nothing
代替原始类型(如Example<Something>
)的接受。 我怎样才能调用这样一个lambda通过仅参考Example<*>
?
Codebase我遇到这个问题: https : //github.com/Jire/Acelta/tree/master/src/main/kotlin/com/acelta/packet/incoming/packets
我正在尝试这个代码,但正如你可以看到在第五行我不能调用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! */) }
这种行为就是星形投影 ( Foo<*>
)在Kotlin中的工作方式。
正如在文档中所述
对于
Foo<T>
,其中T
是具有上限TUpper
的不变类型参数,Foo<*>
相当于读取值的Foo<out TUpper>
,以及写入值的Foo<in Nothing>
。
如果使用星型投影Packet<*>
,则对泛型类型一无所知,因此您不能安全地将任何值传递给需要泛型参数的方法(这就是为什么Nothing
类型)的方法。
您可以使用in-projection为泛型类型指定下限 ,对于Packet<in SomeType>
您将能够将SomeType
实例SomeType
到方法中。 这将需要Packet
实际类型参数为SomeType
或其某些祖先,类似于? super T
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)