我遇到了一些非常基本的问题(以前在Java中从未遇到过),可能是由于我对Kotlin的了解不足。
我当前正在尝试读取YML文件。我以这种方式做到了:
private val factory = YamlConfigurationFactory(LinkedHashMap::class.java, validator, objectMapper, "dw")
Dropwizard最佳配置指南。
https://www.dropwizard.io/1.3.12/docs/manual/testing.html
所以稍后在我的功能中,我会这样做”
val yml = File(Paths.get("config.yml").toUri())
var keyValues = factory.build(yml)
使用调试器时,我可以看到有一个包含key-> values的Map。
现在当我执行keyValues.get(“ my-key”)
type inference failed. the value of the type parameter k should be mentioned in input types
尝试过但没有运气
var keyValues = LinkedHashMap<String, Any>()
keyValues = factory.build(yml)
YamlConfigurationFactory需要一个要映射的类,但我不知道是否有比当前解决方案+ .kotlin更直接的方法来指定Kotlin类,例如
LinkedHashMap::class.java.kotlin
这里也会引发错误。
想法?
答案 0 :(得分:1)
嗯,这是JVM泛型的一个典型问题。 Class<LinkedHashMap>
不包含其键和值的实际类型是什么的信息,因此keyValues
变量总是以类型LinkedHashMap<*, *>
结尾,这仅仅是因为无法在编译时进行检查。有两种解决方法:
这是如何处理标准Java中的问题:只需将LinkedHashMap<*, *>
强制转换为LinkedHashMap<String, Any>
(或任何实际的预期类型)即可。这会产生警告,因为编译器无法验证强制转换是否安全,但是众所周知,在处理JVM泛型和序列化时,这种情况通常是不可避免的。
YamlConfigurationFactory(LinkedHashMap::class.java, ...) as LinkedHashMap<String, Any>
使用Kotlin时,可以通过显式实际创建Class<LinkedHashMap<String, Any>>
实例来避免强制转换。当然,由于这仍然是JVM,因此您会在运行时丢失所有类型信息,但这足以告诉类型推断引擎您的结果是什么。但是,您将需要一个特殊的辅助方法(或者至少我还没有找到一个更简单的解决方案),但是该方法只需在项目中的某个位置声明一次即可。
inline fun <reified T> classOf(): Class<T> = T::class.java
...
val factory = YamlConfigurationFactory(classOf<LinkedHashMap<String, Any>>(), ...)
使用此“ hack”,您将直接获得LinkedHashMap的实例,但是,请始终记住,这只是类型推断引擎的额外信息,但实际上它只是隐藏了不安全的类型转换。另外,如果编译类型(reified
)不知道该类型,则不能使用它。