在Kotlin中推断一个通用types的地图
考虑一下Java类推断它的types的方法如下:
public T readJson(Class c) throws IOException {
这允许做这样的事情:
Map map = foo.readJson(Map.class);
在Java中,它会警告未经检查的强制转换,但它将正常工作。 但是在Kotlin中,这不会那么容易,可以尝试使用:
foo.readJson(Map::class.java)
但是,如果Map
是必需的,它将不起作用:
Type inference failed. Expected type mismatch. required Map found Map!
我也试过定义一个接口StringMap:
interface StringMap : Map
但是,这也不起作用,它会导致这样的例外:
Cannot cast ...LinkedTreeMap to ...StringMap
什么是这样做的正确方法?
Kotlin没有Java原始types(为了后向兼容而留在Java中),因此types系统不允许隐式地进行这种不受控制的赋值( 星号投影 ,最接近Kotlin原始types的概念,保持型号安全)。
您可以对Map
进行未经检查的转换,从而表示您在运行时意识到可能的types不匹配:
@Suppress("UNCHECKED_CAST") val result = foo.readJson(Map::class.java) as Map
您可以抑制未经检查的强制转换警告 ,而不仅仅是一个语句。
这个解决方案的自然改进是编写一个util函数来隐藏未经检查的强制转换:
@Suppress("UNCHECKED_CAST") inline fun JsonReader.readJson(): T { val result = readJson(T::class.java) return result as T }
该解决方案使用带有特定types参数的内联函数 :函数在其每个调用位置被转换和替换,在编译时T
用指定(或推断)types替换。
用法示例:
val map = jsonReader.readJson
fun processMap(map: Map is inferred for this call