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
Scala关键字lazy的理解和使用相关推荐
- Scala中lazy关键字的使用和理解
Scala中lazy关键字的使用和理解 转载声明: 本文转自 Scala中lazy关键字的使用和理解 作者:br0x 转载仅为方便学习查看,一切权利属于原作者,如果带来不便请联系我删除. Scala中 ...
- 【scala】Scala中lazy关键字的使用和理解
Scala中使用关键字lazy来定义惰性变量,实现延迟加载(懒加载). 惰性变量只能是不可变变量,并且只有在调用惰性变量时,才会去实例化这个变量. 在Java中,要实现延迟加载(懒加载),需要自己手动 ...
- scala的lazy
Scala中使用关键字lazy来定义惰性变量,实现延迟加载(懒加载). 惰性变量只能是不可变变量,并且只有在调用惰性变量时,才会去实例化这个变量. 在Java中,要实现延迟加载(懒加载),需要自己手动 ...
- 顶级c程序员之路 基础篇 - 第一章 关键字的深度理解 number-1
c语言有32个关键字,每个关键字你都理解吗? 今天出场的是: auto , register, static, extern 为什么他们会一起呢,说到这里不得不谈到c语言对变量的描述. c给每 ...
- [vue] 说说你对vue的表单修饰符.lazy的理解
[vue] 说说你对vue的表单修饰符.lazy的理解 input标签v-model用lazy修饰之后,vue并不会立即监听input Value的改变,会在input失去焦点之后,才会触发input ...
- 轻量级模型设计与部署总结(关键字定义/架构理解/高效CNN)
点击下方卡片,关注"自动驾驶之心"公众号 ADAS巨卷干货,即可获取 点击进入→自动驾驶之心[模型部署]技术交流群 后台回复[模型部署工程]获取基于TensorRT的分类.检测任务 ...
- scala语言示例_标有示例的Scala关键字
scala语言示例 Scala | 任一关键字 (Scala | Either Keyword) Either is a container similar to the option which h ...
- 对Java单例模式 volatile关键字作用的理解
单例模式是程序设计中经常用到的,简单便捷的设计模式,也是很多程序猿对设计模式入门的第一节课.其中最经典的一种写法是: class Singleton {private volatile static ...
- Scala教程之:深入理解协变和逆变
文章目录 函数的参数和返回值 可变类型的变异 在之前的文章中我们简单的介绍过scala中的协变和逆变,我们使用+ 来表示协变类型:使用-表示逆变类型:非转化类型不需要添加标记. 假如我们定义一个cla ...
- final关键字的深入理解
原文链接:http://www.jianshu.com/p/09b758c4000d 1.final方法在编译阶段绑定,称为静态绑定(static binding),编译时常量,永远不可改变. 2.运 ...
最新文章
- GT Transceiver的总体架构梳理
- java代码编译时修改行为_GitHub - niuzhihua/AST_demo: 利用JavaParser框架在编译时修改语法树(源码)的 demo...
- 斯坦福机器学习公开课学习笔记(2)—监督学习 梯度下降
- red hat 升级 php 5.6,Centos7下编译php5.6.19出错,怎么解决?
- win7域内桌面黑屏
- 如何在Android文本视图周围添加边框?
- C#中使用GDI+实现复杂打印
- html 数组输入框,javascript输入数组
- 【LeetCode】【数组】题号:*304,二维区域和检索
- VTD — 应用于智能驾驶复杂交通场景仿真工具
- 如何在Java项目中定义并调用自己编写的native方法?
- 计算机模拟 matlab,MATLAB计算机模拟实例课件.ppt
- 分布式事务之TCC事务
- DMA驱动框架流程编写
- SOLIDWORKS如何自动生成图纸
- OWASP juice shop靶场闯关题解
- 第三方对接-支付宝支付
- Numpy:数组(Ndarray)操作之数组的转换
- 042期正版四字梅花诗:冰清一洁
- AHPs——algebraic holographic proofs
热门文章
- 弱者都自大暴躁,强者都低调温柔
- win2003桌面图标蓝底去除
- 光辉岁月--beyond 献给麦德拉
- lcs问题java_动态规划法(十)最长公共子序列(LCS)问题
- 打开本地html加载网页慢,网页打开慢怎么办 影响网页打开速度因素有哪些【解决方法】...
- 进入网页就自动弹出层
- 环信Android端实时语音视频通话时在本地实现通话录音录像
- Ubuntu 16.04升级到Ubuntu 16.10的方法:
- 6 errors and 0 warnings potentially fixable with the `--fix` option.
- Sphinx语法设置