Недействительный Mutable Map

  • Java: 1.8.0_102
  • Котлин: 1.0.4

Я пытаюсь создать карту, где вы можете сделать что-то вроде map["key"] += 5 похожее на javascript.

У Kotlin уже есть withDefault который решает одну часть этого, но функция get map по-прежнему возвращает значение с нулевым значением, поэтому я приступил к осуществлению моей собственной реализации, вдохновленной withDefault

 interface NonNullableMutableMap<K,V> : MutableMap<K,V> { override fun put(key: K, value: V): V override fun get(key: K): V } fun <K,V> MutableMap<K,V>.withoutNullValues(default: () -> V): NonNullableMutableMap<K, V> { return NonNullableMapWrapper(this, default) } class NonNullableMapWrapper<K,V>(val map: MutableMap<K,V>, val default: () -> V) : NonNullableMutableMap<K,V> { 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<K, V>> get() = map.entries override val keys: MutableSet<K> get() = map.keys override val values: MutableCollection<V> get() = map.values override fun clear() { map.clear() } override fun putAll(from: Map<out K, V>) { map.putAll(from) } override fun remove(key: K): V { return map.remove(key) ?: default() } } 

Я создал следующий модульный тест, чтобы проверить его

 class NonNullableMapTest { @Test fun notNullableTest() { val map = HashMap<String, Long>().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 

Есть идеи, как решить эту проблему?

Это похоже на ошибку. Я рекомендую сообщить об этом в Kotlin (KT) | YouTrack .

Один из способов обхода – это явно определить set на вашем интерфейсе NonNullableMutableMap . например:

 interface NonNullableMutableMap<K, V> : MutableMap<K, V> { 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 расширения MutableMap.set : https://youtrack.jetbrains.com/issue/KT-14227

Обходной путь не должен использовать += :

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