[英]Casting generic type on Kotlin
我正在嘗試讓mapOf()返回EnumMap,如果K是Enum。 但是,錯誤發生在枚舉(K)的第一個類型變量
碼:
@kotlin.internal.InlineOnly
public inline fun <reified K, V> mapOf(): Map<K, V> =
if (K::class.java.isEnum) EnumMap<K, V>(K::class.java)
else emptyMap()
錯誤:
Type argument is not within its bounds.
Expected: Enum<K!>!
Found: K
我也想給Enum以外的物品,所以reified K: Enum<*>
不能成為解決方案。
使用類型擦除的邪惡作弊:
import java.util.concurrent.TimeUnit // you can use any other enum as well
@Suppress("UNCHECKED_CAST")
public inline fun <reified K, V> mapOf(): Map<K, V> =
if (K::class.java.isEnum)
EnumMap<TimeUnit, V>(K::class.java as Class<TimeUnit>) as Map<K, V>
else emptyMap()
在運行時,這實際上只是EnumMap(K::class.java)
,所有強制轉換都消失了。
沒有干凈的方法使這項工作(afaik),因為使K
符合綁定的K extends Enum<K>
( EnumMap
所需)將需要動態添加綁定到K
,這是不可能的,因為泛型是一個編譯時機制。
在java中,您可以將EnumMap
構造為原始類型,並將其未經檢查轉換為目標類型(即斷言它是正確的)。 但是Kotlin不允許你這樣做,因為它不允許原始類型。 我可以想出一種解決這個限制的方法,即反思:
val constructor = EnumMap::class.constructors.find {
con ->
con.parameters.size == 1
&& con.parameters[0].type.jvmErasure == Class::class
}!!
inline fun <reified K, V> mapOf(): Map<K, V> =
if (K::class.java.isEnum) constructor.call(K::class.java) as Map<K, V>
else emptyMap()
我的Kotlin不是最好的,所以仍有改進的余地。 這是一個可能的解決方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.