如果K为Enum,我试图让mapOf()返回EnumMap。但是,错误发生在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<*>
无法解决问题。
答案 0 :(得分:3)
使用类型擦除的邪恶作弊:
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)
,所有演员都会消失。
答案 1 :(得分:2)
没有 clean 方法来完成这项工作(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并不是最好的,所以仍有改进的余地。这是一种可能的解决方法。