Scala中lazy关键字的使用和理解

转载声明:

本文转自
Scala中lazy关键字的使用和理解
作者:br0x
转载仅为方便学习查看,一切权利属于原作者,如果带来不便请联系我删除。

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

Scala中lazy关键字的使用和理解相关推荐

  1. 【scala】Scala中lazy关键字的使用和理解

    Scala中使用关键字lazy来定义惰性变量,实现延迟加载(懒加载). 惰性变量只能是不可变变量,并且只有在调用惰性变量时,才会去实例化这个变量. 在Java中,要实现延迟加载(懒加载),需要自己手动 ...

  2. scala中def_def关键字以及Scala中的示例

    scala中def Scala def关键字 (Scala def keyword) The def keyword in Scala is used to declare functions and ...

  3. scala中sealed关键字使用指南

    1. 防止继承滥用 ​sealed关键字可以修饰类和特质(特质).密封类提供了一种约束:不能在类定义的文件之外定义任何新的子类.然而,这样做有什么用呢? 在scala源码中List的实现用到了seal ...

  4. scala的lazy

    Scala中使用关键字lazy来定义惰性变量,实现延迟加载(懒加载). 惰性变量只能是不可变变量,并且只有在调用惰性变量时,才会去实例化这个变量. 在Java中,要实现延迟加载(懒加载),需要自己手动 ...

  5. scala语言示例_var关键字与Scala中的示例

    scala语言示例 Scala var关键字 (Scala var keyword) The var Keyword in scala is used to declare variables. As ...

  6. 在Scala中评估val,var,lazy val和def构造时

    发表简短目录 (Post Brief TOC) Introduction介绍 Scala 'val' usageScala" val"用法 How Scala 'val' is E ...

  7. java synchronized_Java中synchronized关键字理解

    好记性不如烂笔头~~ 并发编程中synchronized关键字的地位很重要,很多人都称它为重量级锁.利用synchronized实现同步的基础:Java中每一个对象都可以作为锁.具体表现为以下三种形式 ...

  8. python的上下文管理用哪个关键字_正确理解python中的关键字“with”与上下文管理器...

    正确理解python中的关键字"with"与上下文管理器 来源:中文源码网    浏览: 次    日期:2018年9月2日 [下载文档:  正确理解python中的关键字&quo ...

  9. Scala 中的函数式编程基础(一)

    主要来自 Scala 语言发明人 Martin Odersky 教授的 Coursera 课程 <Functional Programming Principles in Scala>. ...

最新文章

  1. 三亚免税店积分抵现_又变了??三亚免税店的政策又变了~
  2. 解决Xcode The selected destination does not support the architecture 错误错误
  3. Winform中实现自定义水晶按钮控件(附代码下载)
  4. java com dll_通过COM组件方式实现java调用C#写的DLL文件
  5. vmware 虚拟机共享 windows 目录
  6. uva10891Game of sum
  7. 模板——树状数组求逆序对
  8. Android高级控件(一)——ListView绑定CheckBox实现全选,添加和删除等功能
  9. PADS软件如何导出BOM
  10. 【转载】数据库建模工具
  11. 【已解决】Remove redundant parentheses等Python错误大全
  12. T410i开机显示fan error修复
  13. 单片机——BH1750光照传感器篇
  14. 李沐精读论文:MAE 《Masked Autoencoders Are Scalable Vision Learners》
  15. STM32L系列简介
  16. 白炽灯护眼还是LED护眼?盘点led护眼灯品牌排行
  17. linux毫米波雷达程序,用毫米波雷达数据做SLAM
  18. 有一个棋盘,有64个方格,在第一个方格里面放1粒芝麻重量是0.00001kg,第二个里面放2粒,第三个里面放4,棋盘上放的所有芝麻的重量
  19. 读卡耐基《人性的弱点》总结
  20. 手把手带你去搭建一套OpenStack云平台

热门文章

  1. JavaScript学习笔记——JS基础9
  2. 在X86平台上安装摄像头驱动及应用
  3. Android性能测试手段和工具
  4. 我终于迈出了第一步——vue组件封装(分离)
  5. PotPlayer播放器中英双字幕设置
  6. Excel如何每隔几行对数据进行求和
  7. C# 没有注册类 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG))
  8. vim查找字符串-全词匹配、不区分大小写
  9. linux磁盘是vda,linux磁盘分区格式化-fdisk命令工具
  10. linux oracle home 环境变量,在Linux下查看环境变量