Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generic programming 如何在Kotlin中检查泛型类型_Generic Programming_Kotlin - Fatal编程技术网

Generic programming 如何在Kotlin中检查泛型类型

Generic programming 如何在Kotlin中检查泛型类型,generic-programming,kotlin,Generic Programming,Kotlin,我正在测试Kotlin中的泛型类型 if (value is Map<String, Any>) { ... } 使用Kotlin 0.4.68 我在这里遗漏了什么?问题是类型参数被删除,因此无法对照完整的类型映射进行检查,因为在运行时没有关于这些字符串和任何类型的信息 要解决此问题,请使用通配符: if (value is Map<*, *>) {...} 如果(值是Map){…} JVM删除泛型类型信息。但科特林已经具体化了仿制药。如果您有一个泛型类型T,您可以将

我正在测试Kotlin中的泛型类型

if (value is Map<String, Any>) { ... }
使用Kotlin 0.4.68


我在这里遗漏了什么?

问题是类型参数被删除,因此无法对照完整的类型映射进行检查,因为在运行时没有关于这些字符串和任何类型的信息

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

if (value is Map<*, *>) {...}
如果(值是Map){…}

JVM删除泛型类型信息。但科特林已经具体化了仿制药。如果您有一个泛型类型T,您可以将内联函数的类型参数T标记为具体化,以便它能够在运行时检查它

因此,您可以:

inline fun <reified T> checkType(obj: Object, contract: T) {
  if (obj is T) {
    // object implements the contract type T
  }
}
inline-fun-checkType(obj:Object,contract:T){
if(obj是T){
//对象实现契约类型T
}
}

我认为这是更合适的方法

inline fun <reified T> tryCast(instance: Any?, block: T.() -> Unit) {
    if (instance is T) {
        block(instance)
    }
}
inline fun tryCast(实例:Any?,块:T.()->Unit){
if(实例为T){
块(实例)
}
}
用法

//myVar可为空
tryCast(myVar){
//该怎么办。
this.canDoSomething()
}
另一种较短的方法

inline fun <reified T> Any?.tryCast(block: T.() -> Unit) {
    if (this is T) {
        block()
    }
}
inline fun Any?.tryCast(块:T.()->单位){
如果(这是T){
块()
}
}
用法

//myVar可为空
myVar.tryCast{
//该怎么办。
this.canDoSomething()
}

我用
tryCast
尝试了上面的解决方案,我想,在我的具体任务中,列出了许多涉及到的铸件,这并不是什么好主意,因为它大大降低了性能

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

 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?>?) {

}
fun foo(){
val-map:map=mapOf()
map.forEach{entry->
何时(entry.value){
是字符串->{
doSomeWork(entry.key、entry.value作为字符串)
}
是数组->{
doSomeWork(entry.key,(entry.value作为数组)?.map{
如果(它是字符串){
信息技术
}否则无效
}?.toList())
}
}
}
}
私人娱乐doSomeWork(键:String?,值:String){
}
私人娱乐doSomeWork(键:字符串?,值:列表?){
}

太棒了!那太好了!我只是被文档中的示例弄糊涂了:如果您真的想检查某个东西是否是
集合
以使其自动转换,该怎么办?我有这样的代码片段
if(it.getSerializable(ARG_PARAMS)是HashMap){it.getSerializable(ARG_PARAMS)作为HashMap}else null
。所以基本上,如果我检查泛型类型,它会尝试将
HashMap
转换为
HashMap
。我遗漏了什么吗?@FARID是的,会的,而且这种类型的强制转换是不安全的。你能举例说明如何调用
checkType()
?我不确定第二个参数应该传递什么。@MichaelOsofsky
checkType(MyMapOfstring,Map)
为什么这样的东西在kotlin stdlib中不直接可用:-(难道
与?String
不一样吗?@DaliborFilus nope.
后面的问号不一样。这是关于泛型和运行时被擦除的类型。如果你不需要处理泛型,你可以直接使用
作为?
,正确。
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()
}
 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?>?) {

}