如何在Kotlin中检查泛型类型


79

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

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

但是编译器抱怨

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

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

if (value is String) { ... }

使用Kotlin 0.4.68。

我在这里想念什么?

Answers:


91

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

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

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

大!完美的作品!我只是对文档中的示例感到困惑:confluence.jetbrains.net/display/Kotlin/Type+casts
PhilippBrüll2012年

49
如果您实际上想检查某事物是否Collection<String>可以自动投射怎么办?
beruic

我有这样的片段if (it.getSerializable(ARG_PARAMS) is HashMap<*, *>) {it.getSerializable(ARG_PARAMS) as HashMap<String, String>} else null。所以基本上HashMap<String, Integer>HashMap<String, String>如果我要检查泛型类型,它将尝试转换为。我想念什么吗?
Farid

@FARID是的,会的,这种类型的演员转换并不安全
安德烈·布雷斯拉夫

16

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

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

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

1
您可以举一个如何打电话的例子checkType()吗?我不确定第二个参数要传递什么。
Michael Osofsky

9

我认为这是更合适的方式

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()
}

为什么这样的东西在kotlin stdlib中不直接可用:-(
ATom

something as? String一样吗 注意后面的问号as吗?
达利博尔·菲罗斯

@DaliborFilus没有。这与运行时的泛型和已擦除类型有关。如果您不必处理泛型,则可以使用as?,更正。
stk
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.