延迟初始化(Lazy vals)

除了前面介绍的预先初始化成员值外,你还是让系统自行决定何时初始化成员的初始值,这是通过在 val 定义前面添加 lazy(懒惰),也是说直到你第一次需要引用该成员是,系统才会去初始化,否则该成员就不初始化(这也是 lazy 的由来:-)).首先我们定义一个正常定义 val 的例子:


object Demo {val x = { println("initializing x"); "done"}
}

我们首先引用 Demo,然后 Demo.x


scala> Demo
initializing x
res0: Demo.type = Demo$@78178c35scala> Demo.x
res1: String = done

正如你所看到的,当引用 Demo 对象时,它的成员 x 也会初始化,初始化 x 伴随着初始化 Demo 的过程。然后,如果我们在 val x 前添加 lazy ,情况就有所不同了:


object Demo {lazy val x = { println("initializing x"); "done"}
}defined object Demoscala> Demo
res0: Demo.type = Demo$@7de1c412scala> Demo.x
initializing x
res1: String = done

在使用 lazy 之后,初始化 Demo 时,不会初始化 x,只有在引用到 Demo.x 该初始化代码才会执行。这有点类似定义了一个无参数的方法,但和 def 不同的是,lazy 变量初始化代码只会执行一次。通过这个例子,我们可以看到例如 Demo 的对象本身也像一个 lazy 变量,也是在第一次引用时才会初始化,这是正确的,实际上一个 object 定义可以看成是使用了lazy val定义一个匿名类实例的简化方式。

使用l azy val,我们可以修改之前的 RationalTrait, 在这个新的 Trait 定义中,所有的类成员变量的实现(非抽象成员)都使用 lazy 来修饰。


trait LazyRationalTrait{val numerArg :Intval denomArg :Intlazy val numer = numerArg/glazy val denom = denomArg/gprivate lazy val g = {require(denomArg !=0)gcd(numerArg,denomArg)}private def gcd(a:Int,b:Int):Int =if(b==0) a else gcd(b, a % b)override def toString = numer + "/" + denom
}

同时我们把 require 移动到 g 里面,这样所有的 lazy val 初始化代码都移动到 val 定义的右边。我们不再需要预先初始化成员变量。测试如下:


scala> val x = 2
x: Int = 2scala> new LazyRationalTrait{val numerArg = xval denomArg = 2 * x
}res2: LazyRationalTrait = 1/2

我们来分析一下这段代码中命令行的执行顺序:

  1. 首先,创建了一个新的 LazyRationalTrait 的实例,执行 LazyRationalTrait 的初始化代码,这部分代码为空,LazyRationalTrait 所有成员变量都没有初始化。
  2. 其次,该 Trait 的匿名子类的主构造函数被执行,这部分初始化 numberArg 和 denomArg 为2和4.
  3. 接下来,命令行需要调用该实例的 toString 方法来显示该实例的值。
  4. 接下来,toString 需要访问成员 number 这是第一次访问该成员,因此 lazy val 初始化代码被执行。初始化代码调用私有成员g,因此需要计算 g 的值,用到之前定义过的 numberArg 和 denomArg。
  5. 接下来 toString 需要访问成员 denom 这是第一次访问该成员,因此 lazy val 初始化代码被执行。初始化代码调用私有成员 g ,因此需要计算 g 的值,因为 g 已经计算过,无需再计算。
  6. 最后,toString 的结果1/2构造出来并显示。

在这个例子中,我们在写代码时,g 定义在 number 和 denom 的后面,然而,由于这三个变量都是使用 lazy 来定义的,因此它们在代码中出现的顺序并不重要。

Scala中的延迟初始化(Lazy vals)相关推荐

  1. java并发中的延迟初始化

    不安全的延迟初始化示例: Java代码   public class UnsafeLazyInitialization { private static Resource resource; publ ...

  2. 【CSharp】延迟初始化(Lazy)

    参考 https://www.jb51.net/article/202143.htm 1. 什么是延迟初始化 延迟初始化是一种将对象的创建延迟到第一次需要用时的技术,换句话说,对象的初始化是发生在真正 ...

  3. 合理利用延迟初始化优化 Spring Boot

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | 公众号「码农小胖哥」 1. 前言 随着我们项目 ...

  4. Kotlin实战指南九:延迟初始化

    转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/93764289 本文出自[赵彦军的博客] 高阶函数 lateinit 延迟初始化 ...

  5. java 延迟初始化_Java - 延迟初始化

    延迟初始化(lazy initialization),也就是在真正被使用的时候才开始初始化的技巧. 不论是静态还是实例,都可以进行延迟初始化. 其本质是初始化开销和访问开销之间的权衡. 毕竟是一种优化 ...

  6. Spring:延迟初始化

    ApplicationContext实现的默认行为就是在启动时将所有singleton bean提前进行实例化.提前实例化意味着作为初始化过程的一部分,ApplicationContext实例会创建并 ...

  7. spring的延迟初始化bean (default-lazy-init 与 lazy-init )

    ApplicationContext实现的默认行为就是在启动时将所有singleton bean提前进行实例化.提前实例化意味着作为初始化过程的一部分,ApplicationContext实例会创建并 ...

  8. scala学习笔记-过程、lazy值和异常(6)

    过程 在Scala中,定义函数时,如果函数体直接包裹在了花括号里面,而没有使用=连接,则函数的返回值类型就是Unit.这样的函数就被称之为过程.过程通常用于不需要返回值的函数. 过程还有一种写法,就是 ...

  9. 【Kotlin】属性 与 幕后字段 ( 属性声明 | 属性初始化器 | 属性访问器 | field 属性幕后字段 | lateinit 延迟初始化属性 )

    文章目录 I . 属性 字段 总结 II . 属性声明 III . 属性初始化器 IV . get / set 属性访问器 V . 属性幕后字段 field VI . 变量和常量的区别 VII . 延 ...

最新文章

  1. Linux下的内存对齐函数
  2. Docker Compose 配置文件详解
  3. 由浅入深:自己动手开发模板引擎——解释型模板引擎
  4. 解决ubuntu软件安装依赖关系
  5. 51CTO大赛,欢迎投博主一票
  6. 需要使用Git branch switch 的情况Git stash的使用时机
  7. STM8S——watchdog(IWDG)
  8. js一键批量打印_JS 实现选中内容批量打印/导出
  9. html 设置origin,background-origin属性怎么用
  10. uniapp 复制剪贴板
  11. 裁员潮来袭,如何度过这两年“艰苦岁月”
  12. 机器学习项目一:共享单车
  13. 证件照背景色怎么换白色?这两个小技巧要掌握
  14. 基于Pubmed数据库的蛋白质修饰后的信息挖掘
  15. 学生成绩管理系统 ssm layui
  16. [渝粤教育] 广东-国家-开放大学 21秋期末考试大学英语210262k2 (2)
  17. 联接+AI,华为用智能联接为智能时代加速
  18. 单片机学习笔记 —— 8位数码管动态扫描
  19. 安超云生态 | 安超云与百信完成产品兼容互认证 携手打造协同生态
  20. 数据安全平台建设思路

热门文章

  1. id int primary key auto_increment是什么意思
  2. (*长期更新)软考网络工程师学习笔记——Section 10 网络安全
  3. js微信抢红包脚本代码_使用AutoJs实现微信抢红包的代码
  4. flask执行python脚本_如何在Flask中运行python脚本
  5. STM32 ADC采样使用内部参考电压
  6. mysql 优化器不准_mysql 优化器有哪些可选开关
  7. css画带边框三角形,纯CSS画三角形(带边框)
  8. word域变成正常文本_word文档中打钩的8种方法!(全网最全)
  9. 管理服务器一般的作用,管理服务器作用
  10. 跑python gpu利用率低_训练效率低?GPU利用率上不去?快来看看别人家的tricks吧~...