转自:https://yerias.github.io/2020/03/19/scala/3/#3%EF%BC%9Alazy%E4%BF%AE%E9%A5%B0%E7%AC%A6%E5%8F%AF%E4%BB%A5%E4%BF%AE%E9%A5%B0%E5%8F%98%E9%87%8F%EF%BC%8C%E4%BD%86%E6%98%AF%E8%BF%99%E4%B8%AA%E5%8F%98%E9%87%8F%E5%BF%85%E9%A1%BB%E6%98%AFval%E4%BF%AE%E9%A5%B0%E7%9A%84

1:内容是否可变:val修饰的是不可变的,var修饰是可变的

下面看一段代码,你猜是否有错误

  1. 对象 ValAndVar { // val修饰由不可变性必须初始化val LOVE:字符串 = _ var SEX:字符串 = _
  2.  
  3. def mainargs Array [ String ]): Unit = {
  4.  
  5. val name = tunan var age = 18
  6.  
  7. // val修饰因不可伸缩不能重新赋值值
  8. name = zhangsan
  9. age = 19
  10. }
  11. }

真实结果:

  1. val是不可变的,所以修饰的变量必须初始化
  2. val是不可变的,所以修饰的变量不能重新赋值
  3. val是不可变的,所以是多线程安全的
  4. val是不可变的,不用担心会改变它修饰的对象的状态
  5. val是不可变的,增强了代码的附加性,不用担心它的内容发生变化
  6. var是可变的,可以增强代码的补充,和val互补

2:val修饰的变量在编译后放入java中的中的变量被final修饰

  1. 先看源代码

    1. 对象 ValAndVar { val LOVE String = “篮球” var SEX String = _
    2.  
    3. def main(参数: Array [ String ]):单位 = { val名称: String = tunan var age Int = 18 }}
  2. 再看反编译后的代码(只保留了我们想要的部分)

    1. public final class ValAndVar $ {
    2. public static ValAndVar $ MODULE $; 私有最终的String LOVE ; public void mainString [] args){ 字符串名称= tunan”; 年龄= 18 ; } }

    同时字节码(bytecode)不表达一个局部变量是不可变的(immutable),答案是正确的,对于val或者final都只是给编译器用的,编译器如果发现你给此变量重新赋值会引发错误。的能力。我们发现这段代码很奇怪异,scala中的类变量,在字节码转换转换成parifate final,而main方法中的变量却没有添加final修饰,这是否证明编译器有问题?

    所以就有了现在结果。

3:lazy修饰符可以修饰变量,但是这个变量必须是val修饰的

  1. 在证明lazy修饰的变量必须是val之前,我们先看看lazy是什么?

    Scala中使用关键字lazy来定义无限变量,实现连续加载(懒加载)。
    初始化变量只能是不可变变量,并且只能在调用初始化变量时,才会去实例化这个变量。

    在Java中,一般使用get和set实现延迟加载(懒加载),而在Scala中对延迟加载这一特性提供了语法等级的支持:

    1. 惰性 val名称= initName()

    如果不使用lazy关键字对变量修饰,那么变量名称是立即实例化的,下面将通过多个案例对比认识:使用lazy关键字修饰变量后,只有在使用该变量时,才会调用其实例化方法。而在定义名称= initName()时并不会调用initName()方法,只有在后面的代码中使用变量名时才会调用initName()方法。

    不使用lazy修饰的方法:

    1. 对象 LazyDemo { def initName String = { println initialinitName”) return “返回intName } def mainargs Array [ String ]): Unit = { //懒惰的val名称= initName val的名称= initName //程序走到这里,就打印了initName的输出语句 println( “ hello,欢迎来到图南之家”) println(name) //程序走到这里,打印initName的返回值 }}

    结果:上面的名称没有使用lazy关键字进行修饰,所以name是立即实例化的。

    1. 初始化initName
    2. 你好,欢迎来到图南之家
    3. 返回intName

    对象 LazyDemo { def initName: String = { println( “ initialinitName”) return “返回intName” } def main(args: Array [ String ]): Unit = { lazy val name = initName //不调用initName方法,即不打印initName中的输出语句// val name = initName println( “ hello,欢迎来到图南之家”) //打印main方法中的输出语句 println(name) //打印initName的输出语句,打印返回值 }}使用lazy修饰后的方法:

     

    结果:在声明名称时,并没有立即调用实例化方法initName(),甚至在使用名称时,只会调用实例化方法,并且无论调用多少次,实例化方法只会执行一次。

    1. 你好,欢迎来到图南之家
    2. 初始化initName
    3. 返回intName
  2. 证明lazy只能修饰的变量只能使用val

    我们发现名称都是使用val修饰的,如果我们使用var修饰会怎么样呢?

    我们发现报错:'lazy' modifier allowed only with value definitions

    实际上就是认为lazy修饰的变量只能val修饰

scala中的val,var和lazy的更多相关文章

  1. Scala中的类和对象

    类的定义 使用class定义 类的字段 在类中使用var,val定义字段 类的方法 scala中,使用var定义字段默认提供setter和getter方法对应名称为 value_= 和value /* ...

  2. Programming In Scala笔记-第七章、Scala中的控制结构

    所谓的内建控制结构是指编程语言中可以使用的一些代码控制语法,如Scala中的if, while, for, try, match, 以及函数调用等.需要注意的是,Scala几乎所有的内建控制结构都会返 ...

  3. Scala 中的可变(var)与不可变(val)

    引言 Scala 中定义变量分为 var(可变变量)和 val(不可变变量) Scala 中集合框架也分为可变集合和不可变集合.比如 List(列表) 和 Tuple(元组)本身就是不可变的,set ...

  4. scala中lazy

    Scala中通过lazy关键字来定义惰性变量,惰性变量只能是不可变变量.只有在调用惰性变量的时候,才会去实例化这个变量

  5. Scala中Iterator允许执行一次

    背景 使用spark执行mapPartitionsWithIndex((index,iterator)=>{....}),在执行体中将iterator进行一次迭代后,再次根据iterator执行 ...

  6. Scala中的构造器

    Scala中的构造器 Scala中的构造器分为两类,主构造器和辅助构造器 主构造器是通过类名后面跟的括号里加参数列表来定义 辅助构造器是通过关键字this定义 定义一个无参主构造器 class rec ...

  7. Scala中的构造器和高阶函数

    构造器 在定义类时可以定义主构造器.主构造器可以同时声明字段. /** * 主构造器 * @author Administrator */ //在scala中,类和方法交织在一起 class Test ...

  8. Scala中Stream的应用场景及事实上现原理

    欢迎訪问我的独立博客:http://cuipengfei.me/blog/2014/10/23/scala-stream-application-scenario-and-how-its-implem ...

  9. scala中java并发编程

    Runnable/Callable 线程(Thread) Executors/ExecutorService Future 线程安全问题 示例:搜索引擎 解决方案 Runnable/Callable ...

随机推荐

  1. 技术债! 怎样简洁高效的实现多个 Enum 自由转换

    一:背景 1. 讲故事 前段时间和同事负责一个项目的两个业务模块,可能大家缺少沟通,导致本该定义一个 Enum 的地方结果我俩各自定义了一个,导致后面这两个 Enum 进行对接就烦了,为了方便理解,也 ...

  2. 推荐4款个人珍藏的IDEA插件!帮你写出不那么差的代码

    @ 目录 Codota:代码智能提示 代码智能补全 代码智能搜索 Alibaba Java Code Guidelines:阿里巴巴 Java 代码规范 手动配置检测规则 使用效果 CheckStyl ...

  3. 请勿过度依赖Redis的过期监听!!

    作者:迪壳 https://juejin.im/post/6844904158227595271 Redis 过期监听场景 业务中有类似等待一定时间之后执行某种行为的需求 , 比如 30 分钟之后关闭 ...

  4. 一文秒懂!Python字符串格式化之format方法详解

    format是字符串内嵌的一个方法,用于格式化字符串.以大括号{}来标明被替换的字符串,一定程度上与%目的一致.但在某些方面更加的方便 1.基本用法 1.按照{}的顺序依次匹配括号中的值 s = &q ...

  5. HEAP CORRUPTION DETECTED:after Normal block错误方法解决

    一:问题描述: 出现的问题如下: 二:问题产生的原因说明 该问题发生于操作堆内存的时候.产生该问题的原因是:你实际使用的内存大小超出了你实际申请的内存大小,在释放内存的时候就会发生该问题. 举个例子: ...

  6. Lombda表达式(四)

    /* * 自定义函数式接口: * 1.声明一个接口,只能包含一个抽象方法 * 2.给这个接口加@FunctionalInterface */ public class Test { public st ...

  7. webpack4的安装使用

    1.全局安装Webpack 安装到全局后你可以在任何地方共用一个 Webpack 可执行文件( 也就是说可以直接在终端使用webpack的命名 ,例如:webpack --config webpack ...

  8. STM32入门系列-STM32外设地址映射

    片上外设区分为四条总线,根据外设速度的不同,不同总线挂载着不同的外设,APB1挂载低速外设,APB2和AHB挂载高速外设.相应总线的最低地址我们称为该总线的基地址,总线基地址也是挂载在该总线上的首个外 ...

  9. scrapyd部署、使用Gerapy 分布式爬虫管理框架

    Scrapyd部署爬虫项目 GitHub:https://github.com/scrapy/scrapyd API 文档:http://scrapyd.readthedocs.io/en/stabl ...

  10. IOCP 模型2 AcceptEx

    // IOCP2.cpp : Defines the entry point for the console application. // #include "stdafx.h" ...