簡體   English   中英

在Kotlin上投射通用類型

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM