JavaScala关键字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时,才会调用实例化方法,并且无论缩少次调用,实例化方法只会实施3回。

与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第1遍被访问时才调用该措施。

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

相关文章