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進行反編譯,可以看到內容如下:
這樣就驗證了我們的猜想。