对于委托接口,Kotlin IllegalAccessError 带有 += 和 -=

2024-03-17

我定义了这个类:

class NeverNullMap<K, V>(private val backing: MutableMap<K, V> = mutableMapOf(), val default: () -> V): MutableMap<K, V> by backing {
    override operator fun get(key: K): V = backing.getOrPut(key, default)
}

我可以像这样完美地使用它:

fun main(args: Array<String>) {
    val myMap = NeverNullMap<String, Int> {0}
    println(myMap["test"])
    myMap["test"] = myMap["test"] + 10
    println(myMap["test"])
}

正如预期的那样,输出是:

0
10

但是当我尝试将其更改为:

fun main(args: Array<String>) {
    val myMap = NeverNullMap<String, Int> {0}
    println(myMap["test"])
    myMap["test"] += 10
    println(myMap["test"])
}

I get:

Exception in thread "main" java.lang.IllegalAccessError: tried to access method kotlin.collections.MapsKt__MapsKt.set(Ljava/util/Map;Ljava/lang/Object;Ljava/lang/Object;)V from class Day08Kt
    at Day08Kt.main(Day08.kt:10)

为什么会发生这种情况?

Edit:

深入研究一下反编译的代码,它们都会被编译成完全不同的代码。

在没有的工作版本中+=它被编译为:

  Map var2 = (Map)myMap;
  String var3 = "test";
  Integer var4 = ((Number)myMap.get("test")).intValue() + 10;
  var2.put(var3, var4);

非工作版本被编译为:

MapsKt.set(myMap, "test", ((Number)myMap.get("test")).intValue() + 10);

所以它调用这个函数:https://github.com/JetBrains/kotlin/blob/1.2.0/libraries/stdlib/src/kotlin/collections/Maps.kt#L175 https://github.com/JetBrains/kotlin/blob/1.2.0/libraries/stdlib/src/kotlin/collections/Maps.kt#L175

我仍然不知道为什么会产生错误,只是为什么第一个版本的行为不同。

Edit: YouTrack 报告链接 https://youtrack.jetbrains.com/issue/KT-21724


编辑:是的,这是一个错误,它已与KT-14227 https://youtrack.jetbrains.com/issue/KT-14227:

使用时生成错误代码MutableMap.set with plusAssign操作员


编译后(或反编译,在本例中),MapsKt.set变成了private method:

@InlineOnly
private static final void set(@NotNull Map $receiver, Object key, Object value) {
    Intrinsics.checkParameterIsNotNull($receiver, "$receiver");
    $receiver.put(key, value);
}

这解释了IllegalAccessError.

Now, as to why it is private, I'm only speculating, but I feel like it may be due to this:

@usbpc102 https://stackoverflow.com/users/4284268/usbpc102指出@InlineOnly确实是该方法的原因private https://discuss.kotlinlang.org/t/how-does-synchronized-work/1528/2.

@InlineOnly指定永远不应该直接调用该方法:

指定不应在未内联的情况下直接调用此函数

所以我觉得这是一个需要调用的情况set should已内联,但事实并非如此。

如果调用被内联,您最终会得到与工作版本几乎相同的编译代码,因为该方法仅包含对put.

我怀疑这是由于编译器错误造成的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对于委托接口,Kotlin IllegalAccessError 带有 += 和 -= 的相关文章

随机推荐