转自: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修饰是可变的

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

对象 ValAndVar  { // val修饰由不可变性必须初始化val LOVE:字符串 = _ var SEX:字符串   = _

    def  main(args: Array [ String ]): Unit = {

        val name = “ tunan” var age = 18

        // val修饰因不可伸缩不能重新赋值值
name = “ zhangsan”
age = 19
}
}

真实结果:

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

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

  1. 先看源代码

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

    public final  class  ValAndVar $  {
    public static ValAndVar $ MODULE $; 私有最终的String LOVE ; public void main(String [] 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中对延迟加载这一特性提供了语法等级的支持:

    惰性 val名称= initName()

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

    不使用lazy修饰的方法:

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

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

    初始化initName
    你好,欢迎来到图南之家
    返回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(),甚至在使用名称时,只会调用实例化方法,并且无论调用多少次,实例化方法只会执行一次。

    你好,欢迎来到图南之家
    初始化initName
    返回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. 正式班D12

    2020.10.21星期三 正式班D12 一.目录结构 系统目录结构 目录 文件夹:存放的是具体有哪些文件 文件:存放的就是具体的数据 需要记住的 /dev/cdrom # 光盘设备,光盘里存放的内容 ...

  2. 国产化即时通信系统开发 -- 实现GGTalk的登录界面(Linux、Ubuntu、UOS、中标麒麟)

    距离2013年开源GGTalk以来,7年已经过去了,GGTalk现在有了完整的PC版.安卓版.iOS版(即将发布),以及Xamarin版本. 然而,时代一直在变化,在今天,有个趋势越来越明显,那就是政 ...

  3. STL: set和map的区别、联系、使用

    set是一种关联式容器,其特性如下: set以RBTree作为底层容器 所得元素的只有key(键)没有value(值) 不允许出现键重复 所有的元素都会被自动排序 不能通过迭代器来改变set的值,因为 ...

  4. npm的使用说明

    博主是刚开始写项目的前端小白菜,边学边整理,以供后面的小猿参考,共同进步. 首先: npm的官网地址:https://www.npmjs.com Windows 安装包(.msi) 32 位安装包下载 ...

  5. Go module 本地导包方式

    tip本文只讲关于Go module 本地导包方式,其他请自行查阅 Go module 导包方式,go mod init project-name,会得到一个go.mod文件,此文件是管理依赖的,通常 ...

  6. MongoDB 数据备份和恢复 --- MongoDB基础用法(七)

    数据备份 在Mongodb中我们使用mongodump命令来备份MongoDB数据.该命令可以导出所有数据到指定目录中. mongodump命令可以通过参数指定导出的数据量级转存的服务器. mongo ...

  7. centos8 curl: (35) error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small

    centos8操作系统,curl -k https:/www.xxx.com 报错  curl: (35) error:141A318A:SSL routines:tls_process_ske_dh ...

  8. 如何做可靠的分布式锁,Redlock真的可行么

    本文是对 Martin Kleppmann 的文章 How to do distributed locking 部分内容的翻译和总结,上次写 Redlock 的原因就是看到了 Martin 的这篇文章 ...

  9. XJOI 夏令营501-511测试11 游戏

    Alice和Bob两个人正在玩一个游戏,游戏有很多种任务,难度为p的任务(p是正整数),有1/(2^p)的概率完成并得到2^(p-1)分,如果完成不了,得0分.一开始每人都是0分,从Alice开始轮流 ...

  10. TCP/IP协议与Socket

    1.计算机网络体系结构分层 OSI 参考模型注重"通信协议必要的功能是什么", TCP/IP 则更强调"在计算机上实现协议应该开发哪种程序". 2.TCP/IP ...