[英]how to assign java.util.LinkedHashMap<*, *> to kotlin.collections.Map<*, *>
I have declared a method which takes map as parameter:我已经声明了一个以 map 作为参数的方法:
fun myKotlinMethod(myParameter:Map<String,String>)...
Later I read data from json.后来我从json读取数据。 I get an object of type:
java.util.LinkedHashMap<*, *>
I need to use reflection to invoke myKotlinMethod
.我得到一个类型的对象:
java.util.LinkedHashMap<*, *>
我需要使用反射来调用myKotlinMethod
。 Before that, I test if the value is assignable to myParameter
.在此之前,我测试该值是否可分配给
myParameter
。 I ask parameter type using kotlin reflection and I get kotlin.collections.Map<*, *>
.我使用 kotlin 反射询问参数类型,然后得到
kotlin.collections.Map<*, *>
。
bottom line is that java.util.LinkedHashMap<*, *>
does not implement kotlin.collections.Map<*, *>
(it cannot) and therefore is not assignable.底线是
java.util.LinkedHashMap<*, *>
没有实现kotlin.collections.Map<*, *>
(它不能),因此不可分配。
I'm using this method to check assignability我正在使用这种方法来检查可分配性
inline fun isAssignable(parameterType: KType, valueType: KType): Boolean {
if (parameterType == valueType) return true
return parameterType.isSubtypeOf(valueType)
}
and I test like我测试像
if (isAssignable(parameter.type.classifier!!.starProjectedType, parameterValue::class.starProjectedType))
I read about some dark magic kotlin does to collection during compile time, but during runtime, java classes should be used.我读到了一些关于 kotlin 在编译期间收集的黑魔法,但在运行时,应该使用 java 类。 This is not my case since I get kotlin classes in runtime.
这不是我的情况,因为我在运行时获得了 kotlin 类。
So, How do I correctly check for collection types compatibility?那么,如何正确检查集合类型的兼容性?
You seem to have written this the other way around:您似乎以相反的方式写了这个:
// you can even delete the parameterType == valueType check
// isSubtypeOf returns true if the types are the same
return parameterType.isSubtypeOf(valueType)
The method call is valid if the type of the value is a subtype of the parameter type, so it should be:如果值的类型是参数类型的子类型,则方法调用有效,因此应该是:
return valueType.isSubtypeOf(parameterType)
However, note that this is not safe at all.但是,请注意,这根本不安全。 Since you only know that the value is a
LinkedHashMap<*, *>
, what if the map has Int
s, Double
s, or UUID
s in it?既然你只知道值是
LinkedHashMap<*, *>
,那么如果地图中有Int
、 Double
或UUID
怎么办? That would still pass the subtype check.那仍然会通过子类型检查。 Because you used
starProjectedType
on the parameter type, you threw away the <String, String>
part of the type, and didn't actually check that the value actually only has strings.因为您在参数类型上使用了
starProjectedType
,所以您丢弃了类型的<String, String>
部分,并且实际上并没有检查该值是否实际上只有字符串。
To make sure that the collections are compatible, you should also check the collection's elements:为了确保集合兼容,您还应该检查集合的元素:
fun isAssignableToMapStringString(value: Any) =
if (value is Map<*, *>) {
value.all { it.value is String && it.key is String }
} else {
false
}
It can be quite hard to generalise this to any KType
though.但是,很难将其推广到任何
KType
。 You'd have to do a lot of reflection to get the elements out of the collection.您必须进行大量反思才能将元素从集合中取出。 And you'd have to handle maps and collections separately, since
Map
and Collection
are unrelated interfaces :(而且您必须分别处理地图和集合,因为
Map
和Collection
是不相关的接口:(
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.