如何转换Java Map以在Kotlin中读取它?

时间:2019-07-15 14:39:33

标签: kotlin

我遇到了一些非常基本的问题(以前在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

这里也会引发错误。

想法?

1 个答案:

答案 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)不知道该类型,则不能使用它。