如何检查Kotlin中的泛型类型

Phi*_*üll 55 generic-programming kotlin

我正在尝试在Kotlin中测试通用类型.

if (value is Map<String, Any>) { ... }
Run Code Online (Sandbox Code Playgroud)

但编译器抱怨

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

普通类型的检查效果很好.

if (value is String) { ... }
Run Code Online (Sandbox Code Playgroud)

使用Kotlin 0.4.68.

我在这里错过了什么?

And*_*lav 71

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

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

if (value is Map<*, *>) {...}
Run Code Online (Sandbox Code Playgroud)

  • 如果你真的想检查某个东西是`Collection <String>`以使其自动转换怎么办? (36认同)

Vla*_*lad 19

我认为这是更合适的方式

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

用法

// myVar is nullable
tryCast<MyType>(myVar) {
    // todo with this e.g.
    this.canDoSomething()
}
Run Code Online (Sandbox Code Playgroud)

另一种更短的方法

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

用法

// myVar is nullable
myVar.tryCast<MyType> {
    // todo with this e.g.
    this.canDoSomething()
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么这样的东西不能直接在 kotlin stdlib 中使用:-( (2认同)

小智 9

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

因此,您可以执行以下操作:

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

  • 您能举例说明如何调用“checkType()”吗?我不确定第二个参数应该传递什么。 (3认同)