lazy关键字可以用来修饰不可变变量,该关键字的作用是:当对象被真正使用的时候才会被初始化。经常用于一些可能用到也可能用不到的情形,例如:创建一个Connection对象,或者自定义一个可能用到的函数。
lazy的底层编译是如何实现的?
以最简单的如下代码为例:
class Goo {
lazy val goo = "hello"
}
用scalac进行编译之后,再用jad进行反编译,结果如下:
public class Goo {
public static void main(String args[]) {
Goo$.MODULE$.main(args);
}
private String goo$lzycompute() {
synchronized(this) {
if(!bitmap$0) {
goo = "hello";
bitmap$0 = true;
}
}
return goo;
}
public String goo() {
return bitmap$0 ? goo : goo$lzycompute();
}
public Goo() { }
private String goo; private volatile boolean bitmap$0;
}
从编译的角度来看,lazy的实现基本就是用一个异步方法包装的,很类似我们日常在Java中封装了一个方法,在方法中实现了对象的实例化。从而避免对象直接实例化。那么可以推测,在实际使用lazy变量goo的时候,实际使用的,是调用的goo()方法。
我们在代码中加点内容验证一下:
class Goo { lazy val goo = "hello"}
object Goo {
def main(args: Array[String]): Unit = {
val o = new Goo()
print(o.goo)
}
}
然后对Goo.scala进行编译之后,会产生Goo.class和Goo$.class。
我们对Goo$.class进行反编译,可以看到内容如下:
这样就验证了我们的猜想。