Scala关键字lazy的懂得和采取

Scala中利用要字lazy来定义惰性变量,实现延迟加载(懒加载)。
惰性变量只能是不可变变量,并且只有以调用惰性变量时,才会错过实例化这个变量。

每当Java中,要促成延迟加载(懒加载),需要团结手动实现。一般的做法是这般的:

public class LazyDemo {

  private String property;

public String getProperty() {
  if (property == null) {//如果没有初始化过,那么进行初始化
    property = initProperty();
  }
  return property;
}

  private String initProperty() {
    return "property";
  }
}

遵照常用之单例模式懒汉式实现时便下了点类似之笔触实现。

若在Scala中对延缓加载这同样特点提供了语法级别的支撑:

lazy val property = initProperty()

运lazy关键字修饰变量后,只有在用该变量时,才见面调用其实例化方法。也就是说在概念property=initProperty()时连无见面调用initProperty()方法,只有以末端的代码中以变量property时才见面调用initProperty()方法。

假若无使用lazy关键字对变量修饰,那么变量property是立即实例化的:

object LazyOps {

    def init(): String = {
        println("call init()")
        return ""
    }

    def main(args: Array[String]) {
        val property = init();//没有使用lazy修饰
        println("after init()")
        println(property)
    }

}

点的property没有动用lazy关键字展开修饰,所以property是及时实例化的,如果观察程序的出口:

call init()
after init()

好发现,property声明时,立即开展实例化,调用了`init()“实例化方法

比方使以lazy关键字展开修饰:

object LazyOps {

    def init(): String = {
        println("call init()")
        return ""
    }

    def main(args: Array[String]) {
        lazy val property = init();//使用lazy修饰
        println("after init()")
        println(property)
        println(property)
    }

}

着眼输出:

after init()
call init()

以声明property时,并从未即时调用实例化方法intit(),而是以运用property时,才见面调用实例化方法,并且无论缩少次调用,实例化方法才见面执行同样糟糕。

同Java相比起来,实现懒加载确实于便于了。那么Scala是怎样贯彻此语法糖的啊?反编译看下Scala生成的class:

private final String property$lzycompute$1(ObjectRef property$lzy$1, VolatileByteRef bitmap$0$1)
  {
    synchronized (this)//加锁
    {
      if ((byte)(bitmap$0$1.elem & 0x1) == 0)//如果属性不为null
      {//那么进行初始化
        property$lzy$1.elem = init();bitmap$0$1.elem = ((byte)(bitmap$0$1.elem | 0x1));
      }
      return (String)property$lzy$1.elem;
    }
  }

Scala同采取了Java中常用的懒加载的法子自行帮助我们兑现了延期加载,并且还加锁避免多独线程同时调用初始化方法恐怕造成的无一致问题。

借鉴崔鹏飞的小结

于如此一个表达式: lazy val t:T = expr
无论expr是呀事物,字面量也好,方法调用也好。Scala的编译器都见面将此expr包在一个主意中,并且很成一个flag来支配才在t第一蹩脚给看时才调整用该方式。

本文的编借鉴了剥开Scala的糖衣(5) —
Lazy

相关文章