[英]Why does 'get' method of class 'Map' enable sending a not relevant key without a compilation error?
我只是在我的程序中有一个错误,但我根本不明白该程序是如何编译的!
我有以下变量:
gamesPerCountriesMap: MutableMap<Long, MutableMap<Long, MutableList<AllScoresGameObj>>>?
我有以下代码行:
var gamesList = gamesPerCountriesMap?.get(countryItem.id)?.get(competitionItem)
正确的行应该是:
var gamesList = gamesPerCountriesMap?.get(countryItem.id)?.get(competitionItem.id)
我查看了 Map 类的原型,该方法声明如下:
公共内联运算符 fun <@kotlin.internal.OnlyInputTypes K, V> Map<out K, V>.get(key: K): V?
正如我们所看到的,它可以获取 K 并且它是子类型,但是作为 CompetitionObj 类的 instacne 的竞争项并没有继承Long类。 那么为什么编译器没有阻止这个错误呢? 我解决了这个问题,但我很清楚什么没有阻止代码被编译?
Map
接口有两种get
方法。
一种是直接在接口主体中定义的:
Map<K, V> { fun get(key: K): V? }
另一个(您在问题中引用) - 作为扩展函数:
fun <K, V> Map<out K, V>.get(key: K): V?
调用时的重载解析取决于您是否明确指定泛型参数,以及映射K
泛型参数类型与传递的key
参数类型之间的关系:
.get()<Long, MutableList<AllScoresGameObj>.(competitionItem)
,尽管.get()<CompetitionObj, MutableList<AllScoresGameObj>.(competitionItem)
) 会起作用,因为在这个get
重载中有不安全的转换)。key
传递:
K
类型(或其子类型)的实例 - 第一个重载将被调用Map<out inferredK, V>
并且inferredK
类型参数是传递的key
参数的超类型。 最终,它会得到inferredK
= Any
。 事实上Any
是所有事物的超类型,对任何K
执行val x: Map<out Any, V> = mapOf<K, V>()
是完全合法的。 实际上编译器意识到这是一个微不足道的解决方案并发出编译警告Type inference failed. The value of the type parameter K should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
Type inference failed. The value of the type parameter K should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
(我相信在你的情况下,这个警告也应该如此)。 为什么这在运行时仍然有效? 因为类型擦除。那么,为什么将这个重载版本添加到 stdlib 中呢? 不确定,也许对于某些法律案件,例如:
val k : Base = Derived()
val v = mapOf<Derived, String>().get(k) // will call overloaded variant; will infer K as Base
如果没有这个重载,你就必须手动转换:
val v = mapOf<Derived, String>().get(k as Derived)
为什么有两个get
方法?
val x: kotlin.collections.List<String>= java.util.ArrayList<>()
拥有
open class A
class B
在 Java 中是非法的
List<A> x = new ArrayList<B>();
但在 Kotlin 中绝对正常
val x: List<A> = ArrayList<B>()
至于我期望的Map
示例
错误:类型推断失败。 类型参数 K 的值应在输入类型(参数类型、接收器类型或预期类型)中提及。 尝试明确指定它
自 Kotlin 1.0.0 起类型推断被破坏时
如果真的有问题,很高兴看到您正在使用的代码粘贴和 kotlin 编译器版本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.