考虑以下代码:
val myarray = arrayListOf("hello", "world")
println(myarray)
println(myarray::class.java.name)
val arrayString = mapper.writeValueAsString(myarray)
println(arrayString)
println(arrayString::class.java.name)
val myMap = HashMap<String, String?>()
myMap["key"] = JsonPath.read<String>(arrayString, "$")
println(myMap["key"])
println(myMap["key"]!!::class.java.name)
此代码创建一个包含值“ hello”和“ world”的ArrayList,将列表转换为json字符串,读取json的根元素(这是被告知要返回字符串的通用函数),并将其存储在哈希图
此代码编译并运行无错误,并产生以下输出:
[hello, world]
java.util.ArrayList
["hello", "world"]
java.lang.String
["hello","world"]
net.minidev.json.JSONArray
myMap["key"]
如何返回JSONArray
? (记得myMap被声明为<String, String?>
)
Kotlin的类型在编译时检查,但是由于告知通用函数JsonPath.read
返回一个String
,因此编译会很好。
然后JsonPath.read
似乎违反了合同,并返回了JSONArray
而不是String
。 Kotlin似乎没有键入check,而是允许在JSONArray
中存储Map<String, String?>
。
除非我尝试将myMap["key"]
用作String
注意
此问题可以通过将读取json的行更改为:
myMap["key"] = ObjectMapper().writeValueAsString(JsonPath.read<String>(arrayString, "$"))
编辑
不使用json疯狂的代码示例:
fun <T> myFun(): T {
return 7 as T
}
fun test() {
val map = HashMap<String, String?>()
map["key"] = myFun<String>()
println(map["key"])
println(map["key"]!!::class.java.name)
}
returns:
7
java.lang.Integer
答案 0 :(得分:1)
Generic type information is erased at runtime。
因此,基本上只是以您更新的示例并将其转换为运行时的结果(简化)为例:
<FlatList data={this.state.data} extraData={this.state} .../>
还要注意,您在这里使用的是unchecked cast(并且很可能fun myFun(): Any = 7
fun test() {
val map = HashMap<Any, Any?>()
map["key"] = myFun()
println(map["key"])
println(map["key"]!!::class.java.name) // of course: Integer!
}
也在使用它),这基本上就是编译器没有真正机会抓住问题的原因。或者换句话说,通过使用unchecked cast(JsonPath.read
),您基本上对编译器说:“嘿...我知道我在做什么,不要打扰” ...所以它不会不用理会;-)
答案 1 :(得分:0)
类似的问题被跟踪为https://youtrack.jetbrains.com/issue/KT-12451。
目前,即使Kotlin知道调用类型的泛型类型,在传递给另一个泛型方法之前,Kotlin不会检查泛型方法调用的结果。这种行为与Java中的行为相同,尽管可能还有一些改进的空间。