Pij*_*usn 2 parameters constructor garbage-collection scala
我只是在学习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.
}
}
Run Code Online (Sandbox Code Playgroud)
当然,它更复杂,有参数和东西.这个类假设是一个长寿的类,我只是想确保它没有任何它不需要的引用.
我即将把这个类移植到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.
}
}
Run Code Online (Sandbox Code Playgroud)
再次,它会更复杂,但想法很清楚.那么,问题是:
Scala是否能够检测不再需要哪些构造函数参数(_aSelector以及_bSelector上面的示例中)?或者我是否必须明确清除参考?
_a
_aSelector = null
_b
_bSelector = null
Run Code Online (Sandbox Code Playgroud)
PS我明白GC是检测范围外引用的那个,但Scala编译器是定义变量范围的一个,因此它是一个定义行为.
使用lazy vals,您明确要求_a仅在第一次访问时进行初始化.这需要_aSelector在构造函数结束后保持引用,至少直到_a第一次访问.
然而 - 它让我感到惊讶 - 看起来scalac足够聪明,可以生成在成功初始化_aSelector之后归零的代码_a.
您可以通过以下方式验证scalac -Xprint:mixin:
Test.scala:
class Test(factory: () => Int) {
lazy val x = factory()
}
Run Code Online (Sandbox Code Playgroud)
然后:
$ 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>();
()
}
};
Run Code Online (Sandbox Code Playgroud)
因此,一旦_a第一次访问并成功初始化,是的,_aSelector将发布引用,GC将能够回收它.
| 归档时间: |
|
| 查看次数: |
346 次 |
| 最近记录: |