如何检查Kotlin中的泛型类型

时间:2012-10-31 09:07:47

标签: generic-programming kotlin

我正在尝试在Kotlin中测试泛型类型。

if (value is Map<String, Any>) { ... }

但编译器抱怨

  

无法检查已擦除类型的实例:jet.Map

普通类型的支票效果很好。

if (value is String) { ... }

使用Kotlin 0.4.68。

我在这里缺少什么?

4 个答案:

答案 0 :(得分:58)

问题是类型参数被删除,因此您无法检查完整类型Map,因为在运行时没有关于String和Any的信息。

要解决此问题,请使用通配符:

if (value is Map<*, *>) {...}

答案 1 :(得分:3)

JVM除去通用类型信息。但是科特林对仿制药进行了改良。如果您具有通用类型T,则可以将内联函数的类型参数T标记为已修改,以便可以在运行时对其进行检查。

因此您可以这样做:

inline fun <reified T> checkType(obj: Object, contract: T) {
  if (obj is T) {
    // object implements the contract type T
  }
}

答案 2 :(得分:2)

我认为这是更合适的方法

inline fun <reified T> tryCast(instance: Any?, block: T.() -> Unit) {
    if (instance is T) {
        block(instance)
    }
}

用法

// myVar is nullable
tryCast<MyType>(myVar) {
    // todo with this e.g.
    this.canDoSomething()
}

另一种较短的方法

inline fun <reified T> Any?.tryCast(block: T.() -> Unit) {
    if (this is T) {
        block()
    }
}

用法

// myVar is nullable
myVar.tryCast<MyType> {
    // todo with this e.g.
    this.canDoSomething()
}

答案 3 :(得分:-1)

我已经用 tryCast<Array<String?>> 尝试了上面的解决方案,我想,在我列出涉及许多演员的特定任务中,这并不是什么好主意,因为它大大降低了性能。

这是我最后做的解决方案 - 手动检查条目并调用方法,如下所示:

 fun foo() {
    val map: Map<String?, Any?> = mapOf()
    map.forEach { entry ->
        when (entry.value) {
            is String -> {
                doSomeWork(entry.key, entry.value as String)
            }
            is Array<*> -> {
                doSomeWork(entry.key, (entry.value as? Array<*>)?.map {
                    if (it is String) {
                        it
                    } else null
                }?.toList())
            }
        }
    }
}


private fun doSomeWork(key: String?, value: String) {

}
private fun doSomeWork(key: String?, values: List<String?>?) {

}