这个问题的答案是Scala懒惰val的(隐藏的)代价是什么?展示了它们是如何在Scala 2.7中实现的。但正如评论所说,从那以后,情况肯定发生了变化,所以我很好奇,lazy val
类变量的当前(2.10)实现是什么?
用scala 2.10.2:编译
class Foo {
lazy val bar = math.pow(5, 3)
}
然后用JD-GUI:反编译结果
import scala.math.package.;
import scala.reflect.ScalaSignature;
@ScalaSignature(bytes=" 06 01e1A! 01 02 01 13t 31ai\8 13 03rtq 01P3naRLhh 01 01 24 05 011 01CA 04 13 33 05A!"A 05 02 13M 34 27r\1n 05-A!AB!osJ+grC 03 16 01 21 05a" 01 04=S:LGO 20 13 02 37A 21 01 03A 07 02 05!A! 03 01EC 02 23 051#A 02cCJ, 22 01 06t 03 17UI!A 06 05 03r 21{WO 317f 21!A 02 01#A!B 23! 22 01 022be 02 02")
public class Foo {
private double bar;
private volatile boolean bitmap$0;
private double bar$lzycompute() {
synchronized (this) {
if (!this.bitmap$0) {
this.bar = package..MODULE$.pow(5.0D, 3.0D);
this.bitmap$0 = true;
}
return this.bar;
}
}
public double bar() {
return this.bitmap$0 ? this.bar : bar$lzycompute();
}
}
编辑-以下是三个字段的情况:
class Foo {
lazy val a = math.pow(5, 1)
lazy val b = math.pow(5, 2)
lazy val c = math.pow(5, 3)
}
解压缩:
import scala.math.package.;
import scala.reflect.ScalaSignature;
@ScalaSignature(bytes=" 06 01 052A! 01 02 01 13t 31ai\8 13 03rtq 01P3naRLhh 01 01 24 05 011 01CA 04 13 33 05A!"A 05 02 13M 34 27r\1n 05-A!AB!osJ+grC 03 16 01 21 05a" 01 04=S:LGO 20 13 02 37A 21 01 03A 07 02 05!A! 03 01EC 02 23 051#A 01b+ 05! 02CA 04 26 23t1 02B 01 04E_V 24G. 32 05t1 01At 21)Q 05) 05 21 21rt 05t5 01A) 31!C 01' 05t!r 03 05 35 01! 05t 25) 03 25 03t 21 07 05 03 05 37 01! 25r 21" 01 24 03 05 31 07 02 03 21 01 21 03 05 13 25 02 13 02 05r 04 03")
public class Foo {
private double a;
private double b;
private double c;
private volatile byte bitmap$0;
private double a$lzycompute() {
synchronized (this) {
if ((byte)(this.bitmap$0 & 0x1) == 0) {
this.a = package..MODULE$.pow(5.0D, 1.0D);
this.bitmap$0 = ((byte)(this.bitmap$0 | 0x1));
}
return this.a;
}
}
private double b$lzycompute() {
synchronized (this) {
if ((byte)(this.bitmap$0 & 0x2) == 0) {
this.b = package..MODULE$.pow(5.0D, 2.0D);
this.bitmap$0 = ((byte)(this.bitmap$0 | 0x2));
}
return this.b;
}
}
private double c$lzycompute() {
synchronized (this) {
if ((byte)(this.bitmap$0 & 0x4) == 0) {
this.c = package..MODULE$.pow(5.0D, 3.0D);
this.bitmap$0 = ((byte)(this.bitmap$0 | 0x4));
}
return this.c;
}
}
public double a() {
return (byte)(this.bitmap$0 & 0x1) == 0 ? a$lzycompute() : this.a;
}
public double b() {
return (byte)(this.bitmap$0 & 0x2) == 0 ? b$lzycompute() : this.b;
}
public double c() {
return (byte)(this.bitmap$0 & 0x4) == 0 ? c$lzycompute() : this.c;
}
}
更新Scala 2.12.1(三年后的2016年12月)。
在PR 5294(字段阶段完全扩展延迟val和模块)之后,您可以在提交743f0d2:中读取
懒惰的val没有本地
现在
synchronized
被专门擦除以避免拳击,我们可以放弃这项工作。请注意,这确实在慢速路径上添加了一个额外的cast和getter调用,但这可能无关紧要。
class C { def foo = {lazy val x = {println("a"); "A" }; x } }
变为:
def foo(): String = {
lazy <artifact> val x$lzy: scala.runtime.LazyRef[String] = new scala.runtime.LazyRef[String]();
<artifact> private def x$lzycompute(): String =
x$lzy.synchronized[String]{
if (x$lzy.initialized())
x$lzy.value() // NOTE: gets an `.asInstanceOf[String]` after erasure
else
{
x$lzy.value_=({
scala.Predef.println("a");
"A"
});
x$lzy.initialized_=(true);
x$lzy.value() // NOTE: gets an `.asInstanceOf[String]` after erasure
}
}
lazy def x(): String =
if (x$lzy.initialized())
x$lzy.value() // NOTE: gets an `.asInstanceOf[String]` after erasure
else
x$lzycompute();
x()
}