不可空的可变映射
- 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