我已经定义了这个类:
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)
}
Run Code Online (Sandbox Code Playgroud)
我可以像这样完美地使用它:
fun main(args: Array<String>) {
val myMap = NeverNullMap<String, Int> {0}
println(myMap["test"])
myMap["test"] = myMap["test"] + 10
println(myMap["test"])
}
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,输出是:
0
10
Run Code Online (Sandbox Code Playgroud)
但当我尝试将其更改为:
fun main(args: Array<String>) {
val myMap = NeverNullMap<String, Int> {0}
println(myMap["test"])
myMap["test"] += 10
println(myMap["test"])
}
Run Code Online (Sandbox Code Playgroud)
我明白了:
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)
Run Code Online (Sandbox Code Playgroud)
为什么会这样?
编辑:
将一点点编译成反编译代码都会编译成完全不同的代码.
在没有+=它的工作版本中,它被编译为:
Map var2 = (Map)myMap;
String var3 = "test";
Integer var4 = ((Number)myMap.get("test")).intValue() + 10;
var2.put(var3, var4);
Run Code Online (Sandbox Code Playgroud)
非工作版本编译为:
MapsKt.set(myMap, "test", ((Number)myMap.get("test")).intValue() + 10);
Run Code Online (Sandbox Code Playgroud)
所以它调用了这个函数:https://github.com/JetBrains/kotlin/blob/1.2.0/libraries/stdlib/src/kotlin/collections/Maps.kt#L175
我仍然不知道为什么会产生错误,这就是为什么第一个版本表现不同的原因.
编辑:是的,这是一个错误,它已与KT-14227合并:
MutableMap.set使用withplusAssign运算符时生成错误代码
编译(或反编译,在本例中)后,MapsKt.set变成一个private方法:
@InlineOnly
private static final void set(@NotNull Map $receiver, Object key, Object value) {
Intrinsics.checkParameterIsNotNull($receiver, "$receiver");
$receiver.put(key, value);
}
Run Code Online (Sandbox Code Playgroud)
这解释了IllegalAccessError.
现在,至于为什么它是私有的,我只是猜测,但我觉得可能是因为:
@usbpc102指出这@InlineOnly确实是该方法的原因private。
@InlineOnly指定永远不应该直接调用该方法:
指定不应在未内联的情况下直接调用此函数
所以我觉得在这种情况下,set 应该内联调用,但事实并非如此。
如果调用被内联,您最终会得到与工作版本几乎相同的编译代码,因为该方法仅包含对put.
我怀疑这是由于编译器错误造成的。
| 归档时间: |
|
| 查看次数: |
220 次 |
| 最近记录: |