如何在 Kotlin 中检查泛型类型
Posted
技术标签:
【中文标题】如何在 Kotlin 中检查泛型类型【英文标题】:How can I check for generic type in Kotlin 【发布时间】:2012-10-31 09:07:47 【问题描述】:我正在尝试在 Kotlin 中测试泛型类型。
if (value is Map<String, Any>) ...
但编译器抱怨
无法检查擦除类型的实例:jet.Map
普通类型的检查效果很好。
if (value is String) ...
使用了 Kotlin 0.4.68。
我在这里错过了什么?
【问题讨论】:
【参考方案1】:问题是类型参数被删除了,所以你不能检查完整的类型 Map,因为在运行时没有关于这些 String 和 Any 的信息。
要解决此问题,请使用通配符:
if (value is Map<*, *>) ...
【讨论】:
太棒了!这完全有效!我只是对文档中的示例感到困惑:confluence.jetbrains.net/display/Kotlin/Type+casts 如果您真的想检查某个东西是否是Collection<String>
以使其自动投射,该怎么办?
我有这样的sn-p if (it.getSerializable(ARG_PARAMS) is HashMap<*, *>) it.getSerializable(ARG_PARAMS) as HashMap<String, String> else null
。所以基本上如果我检查泛型类型,它会尝试将HashMap<String, Integer>
转换为HashMap<String, String>
。我错过了什么吗?
@FARID 是的,会的,而且这种演员阵容不安全【参考方案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()
【讨论】:
为什么这样的东西不能直接在 kotlin stdlib 中使用:-(something as? String
不一样吗?注意as
之后的问号?
@DaliborFilus 不。这是关于运行时的泛型和擦除类型。如果你不需要处理泛型,你可以使用as?
,对。【参考方案3】:
JVM 删除了泛型类型信息。但是 Kotlin 已经具体化了泛型。如果你有一个泛型类型 T,你可以将内联函数的类型参数 T 标记为 reified,以便它能够在运行时检查它。
所以你可以这样做:
inline fun <reified T> checkType(obj: Object, contract: T)
if (obj is T)
// object implements the contract type T
【讨论】:
你能举例说明如何调用checkType()
吗?我不确定第二个参数应该传递什么。
@MichaelOsofsky checkType(myMapOfStrings, Map<String, Any>)
【参考方案4】:
我会给出一个变通的解决方案,但我认为它很干净,有点
try
(value as Map<String,Any>?)?.let castedValue ->
doYourStuffHere() //using castedValue
catch(e: Exception)
valueIsNotOfType() //Map<String,Any>
【讨论】:
【参考方案5】:我已经用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?>?)
【讨论】:
以上是关于如何在 Kotlin 中检查泛型类型的主要内容,如果未能解决你的问题,请参考以下文章