不可空的可变映射

  • Java: 1.8.0_102
  • Kotlin: 1.0.4

我试图创建一个地图,你可以做一些像map["key"] += 5类似于JavaScript。

Kotlin已经在withDefault情况下解决了这个问题的一部分,但是map的get函数仍然返回一个可以为空的值,所以我开始用withDefault

 interface NonNullableMutableMap : MutableMap { override fun put(key: K, value: V): V override fun get(key: K): V } fun  MutableMap.withoutNullValues(default: () -> V): NonNullableMutableMap { return NonNullableMapWrapper(this, default) } class NonNullableMapWrapper(val map: MutableMap, val default: () -> V) : NonNullableMutableMap { override fun put(key: K, value: V): V = map.put(key, value) ?: default() override fun get(key: K): V { val value = map.getOrPut(key, default) return value } override val size: Int get() = map.size override fun containsKey(key: K): Boolean = map.containsKey(key) override fun containsValue(value: V): Boolean = map.containsValue(value) override fun isEmpty(): Boolean = map.isEmpty() override val entries: MutableSet<MutableMap.MutableEntry> get() = map.entries override val keys: MutableSet get() = map.keys override val values: MutableCollection get() = map.values override fun clear() { map.clear() } override fun putAll(from: Map) { map.putAll(from) } override fun remove(key: K): V { return map.remove(key) ?: default() } } 

我创建了下面的unit testing来测试它

 class NonNullableMapTest { @Test fun notNullableTest() { val map = HashMap().withoutNullValues { 0 } map["first"] += 10L map["second"] -= 10L assertThat(map["first"]).isEqualTo(10L) assertThat(map["second"]).isEqualTo(-10L) assertThat(map["third"]).isEqualTo(0L) } } 

但是当我运行测试时出现以下错误:

 tried to access method kotlin.collections.MapsKt__MapsJVMKt.set(Ljava/util/Map;Ljava/lang/Object;Ljava/lang/Object;)V from class foo.bar.NonNullableMapTest java.lang.IllegalAccessError: tried to access method kotlin.collections.MapsKt__MapsJVMKt.set(Ljava/util/Map;Ljava/lang/Object;Ljava/lang/Object;)V from class foo.bar.NonNullableMapTest 

任何想法如何解决这个问题?

这看起来像是一个bug。 我建议在Kotlin(KT)|上报告 YouTrack 。

一种解决方法是通过在NonNullableMutableMap接口上显式定义set 。 例如:

 interface NonNullableMutableMap : MutableMap { override fun put(key: K, value: V): V override fun get(key: K): V operator fun set(key: K, value: V) { put(key, value) } } 

关于你得到的运行时错误,目前在+=运算符被内嵌的MutableMap.set扩展函数编译时存在一个错误: https : MutableMap.set

解决方法是不要使用+=

 map["first"] = map["first"] + 10L