gpt4 book ai didi

Scala:清理构造函数参数

转载 作者:行者123 更新时间:2023-12-01 07:45:05 25 4
gpt4 key购买 nike

我刚刚开始学习 Scala,并且担心清理构造函数参数。

在 Java 中我有这样一个类:

public class Example {
private A a;
private B b;

private SelectorA aSelector;
private SelectorB bSelector;

public Example(SelectorA aSelector, SelectorB bSelector) {
this.aSelector = Objects.requireNonNull(aSelector);
this.bSelector = Objects.requireNonNull(bSelector);
}

public void start() {
if (a == null) {
a = aSelector.select();
aSelector = null; // Removing reference.
}

if (b == null) {
b = bSelector.select();
bSelector = null; // Removing reference.
}

// Go on.
}
}

当然,它更复杂,有参数和东西。这个类应该是一个长期存在的类,我只是想确保它不包含任何它不需要的引用。

我即将把这个类移植到 Scala 并制作这样的类:

class Example(_aSelector: Selector[A], _bSelector: Selector[B]) {
private lazy val _a = _aSelector() // Will _aSelector reference be cleared?
private lazy val _b = _bSelector() // Will _bSelector reference be cleared?

def start() = {
// Use _a.
// Use _b.
// Go on.
}
}

同样,它会变得更加复杂,但思路很明确。所以,问题:

Scala 是否能够检测不再需要哪些构造函数参数(上例中的 _aSelector_bSelector)?还是我必须明确清除引用?

_a
_aSelector = null
_b
_bSelector = null

附言我知道 GC 是检测范围外引用的工具,但 Scala 编译器是定义变量范围的工具,因此它是定义行为的工具。

最佳答案

使用 lazy val,您明确要求 _a 仅在第一次访问时被初始化。这需要在构造函数结束后保留​​对 _aSelector 的引用,至少要到第一次访问 _a 为止。

然而——让我感到惊讶的是——scalac 似乎足够聪明,可以在 _a 成功初始化后生成清空 _aSelector 的代码。

您可以使用 scalac -Xprint:mixin 验证这一点:

测试.scala:

class Test(factory: () => Int) {
lazy val x = factory()
}

然后:

$ scalac -Xprint:mixin Test.scala
class Test extends Object {
@volatile private[this] var bitmap$0: Boolean = false;
private def x$lzycompute(): Int = {
{
Test.this.synchronized({
if (Test.this.bitmap$0.unary_!())
{
Test.this.x = Test.this.factory.apply$mcI$sp();
Test.this.bitmap$0 = true;
()
};
scala.runtime.BoxedUnit.UNIT
});
Test.this.factory = null // <-- LOOK HERE
};
Test.this.x
};
<paramaccessor> private[this] val factory: Function0 = _;
lazy private[this] var x: Int = _;
<stable> <accessor> lazy def x(): Int = if (Test.this.bitmap$0.unary_!())
Test.this.x$lzycompute()
else
Test.this.x;
def <init>(factory: Function0): Test = {
Test.this.factory = factory;
Test.super.<init>();
()
}
};

所以,一旦_a被第一次访问,并且初始化成功,,对_aSelector的引用就会被释放, GC 将能够回收它。

关于Scala:清理构造函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26565129/

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