• Java:1.8.0_102
  • Kotlin:1.0.4

  • 我正在尝试创建一个 map ,您可以在其中执行类似于javascript的map["key"] += 5之类的操作。

    Kotlin已经拥有withDefault来解决此问题的一部分,但是map的get函数仍然返回可为空的值,因此我继续根据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接口(interface)上显式定义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)
        }
    }
    

    07-25 23:19
    查看更多