gpt4 book ai didi

带有 += 和 -= 的 Kotlin IllegalAccessError 用于委托(delegate)接口(interface)

转载 作者:IT老高 更新时间:2023-10-28 13:40:29 27 4
gpt4 key购买 nike

我已经定义了这个类:

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"])
}

我明白了:

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)

为什么会这样?

编辑:

稍微研究一下反编译的代码都会被编译成完全不同的代码。

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

  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

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

编辑:YouTrack link to the report

最佳答案

编辑:是的,这是一个错误,它已与 KT-14227 合并:

Incorrect code is generated when using MutableMap.set with plusAssign operator


编译(或反编译,在本例中)之后,MapsKt.set 变成了一个private 方法:

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

这解释了 IllegalAccessError

现在,至于为什么是私有(private)的,我只是猜测,但我觉得可能是因为:

@usbpc102指出 @InlineOnly is indeed the reason for the method being private .

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

Specifies that this function should not be called directly without inlining

所以我觉得这是对 set 应该的调用被内联的情况,但事实并非如此。

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

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

关于带有 += 和 -= 的 Kotlin IllegalAccessError 用于委托(delegate)接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47717542/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com