zoukankan      html  css  js  c++  java
  • scala中的val,var和lazy

    转自: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
         } 
    }

    真实结果:
    val和var的可变性比较

    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修饰

  • 相关阅读:
    Seven Puzzle Aizu
    Cheese
    Curling 2.0
    Ball
    Property Distribution
    Red and Black
    Lake Counting
    Ants
    剑桥雅思写作高分范文ESSAY20
    剑桥雅思写作高分范文ESSAY19
  • 原文地址:https://www.cnblogs.com/hhz-97/p/13019591.html
Copyright © 2011-2022 走看看