gpt4 book ai didi

kotlin - 为什么对象表达式中的代码可以从 kotlin 中包含它的范围访问变量?

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

在 Kotlin 中,对象表达式中的代码可以从包含它的范围内访问变量,就像下面的代码:

fun countClicks(window: JComponent) {
var clickCount = 0
var enterCount = 0
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
clickCount++
}

override fun mouseEntered(e: MouseEvent) {
enterCount++
}
})
}

但是为什么呢?在 Java 中是不允许这样做的,因为对象的生命周期与局部变量不同,所以 enterCountclickCount 可能在你尝试时无效访问对象。谁能告诉我 Kotlin 是如何做到这一点的?

最佳答案

在 Java 中,您只能(有效地)捕获匿名类和 lambda 中的最终变量。在 Kotlin 中,您可以捕获任何变量,即使它们是可变的。

这是通过将任何捕获的变量包装在简单包装类的实例中来完成的。这些包装器只有一个包含捕获变量的字段。由于包装器的实例可以是final,因此可以照常捕获它们。

所以当你这样做时:

var counter = 0
{ counter++ }() // definition and immediate invocation, very JavaScript

这样的事情发生在幕后:

class Ref<T>(var value: T) // generic wrapper class somewhere in the runtime

val counter = Ref(0); // wraps an Int of value 0
{ counter.value++ }() // captures counter and increments its stored value

包装类的实际实现是用Java编写的,如下所示:

public static final class ObjectRef<T> implements Serializable {
public T element;

@Override
public String toString() {
return String.valueOf(element);
}
}

还有称为 ByteRefShortRef 等的附加包装器,它们包装各种原语,这样它们就不必被装箱就可以被捕获。您可以在 this file 中找到所有包装类。 .

积分转到 Kotlin in Action这本书包含此信息的基础知识,以及此处使用的示例。

关于kotlin - 为什么对象表达式中的代码可以从 kotlin 中包含它的范围访问变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44538627/

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