当前位置: 首页 > news >正文

网站建设的目标新手做网站免费教程

网站建设的目标,新手做网站免费教程,大学国际化网站建设,中信建设有限责任公司是国企吗Scala中使用关键字lazy来定义惰性变量,实现延迟加载(懒加载)。 惰性变量只能是不可变变量,并且只有在调用惰性变量时,才会去实例化这个变量。 在Java中,要实现延迟加载(懒加载),需要自己手动实现。一般的做法是这样的…

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也是编译成字节码跑在jvm上的,而jvm的字节码指令并没有提供对lazy这种语义的支持,所以由此可以推断,lazy只是一个语法糖,scala编译器在编译时期对其做一些包装转换,但究竟是如何转换的呢,可以写一段代码编译然后反编译看一下。

编写一段scala代码,有两个变量,一个使用lazy修饰,一个不使用lazy修饰:

package cc11001100.scala.lazyStudyclass LazyInitDemoForDecompilation {lazy val foo = "foo"val bar = "bar"
}object LazyInitDemoForDecompilation {def main(args: Array[String]): Unit = {val o = new LazyInitDemoForDecompilation()println(o.foo)println(o.bar)}}

然后编译为字节码文件,再使用jd-gui等工具将其反编译:

package cc11001100.scala.lazyStudy;import scala.reflect.ScalaSignature;@ScalaSignature(bytes="\006\001}2A!\003\006\001#!)q\003\001C\0011!A1\004\001EC\002\023\005A\004C\004&\001\t\007I\021\001\017\t\r\031\002\001\025!\003\036\017\0259#\002#\001)\r\025I!\002#\001*\021\0259b\001\"\001+\021\025Yc\001\"\001-\005qa\025M_=J]&$H)Z7p\r>\024H)Z2p[BLG.\031;j_:T!a\003\007\002\0231\f'0_*uk\022L(BA\007\017\003\025\0318-\0317b\025\005y\021AC2dcE\002\004'M\0311a\r\0011C\001\001\023!\t\031R#D\001\025\025\005i\021B\001\f\025\005\031\te.\037*fM\0061A(\0338jiz\"\022!\007\t\0035\001i\021AC\001\004M>|W#A\017\021\005y\031S\"A\020\013\005\001\n\023\001\0027b]\036T\021AI\001\005U\0064\030-\003\002%?\t11\013\036:j]\036\f1AY1s\003\021\021\027M\035\021\00291\013'0_%oSR$U-\\8G_J$UmY8na&d\027\r^5p]B\021!DB\n\003\rI!\022\001K\001\005[\006Lg\016\006\002.aA\0211CL\005\003_Q\021A!\0268ji\")\021\007\003a\001e\005!\021M]4t!\r\0312'N\005\003iQ\021Q!\021:sCf\004\"AN\037\017\005]Z\004C\001\035\025\033\005I$B\001\036\021\003\031a$o\\8u}%\021A\bF\001\007!J,G-\0324\n\005\021r$B\001\037\025\001")
public class LazyInitDemoForDecompilation
{private String foo;private String foo$lzycompute(){// 因为在调用此方法之前已经判断过一次标志位的值了,// 所以可以看做是一种被拆散了的DCLsynchronized (this){if (!this.bitmap$0){this.foo = "foo";this.bitmap$0 = true;}}return this.foo;}public String foo(){// 每次获取foo的值的时候,先判断是否已经初始化过了,// 如果还没有初始化就将其初始化,否则直接将已经计算出的值返回return !this.bitmap$0 ? foo$lzycompute() : this.foo;}public String bar(){return this.bar;}// bar变量直接为其赋值的private final String bar = "bar";// 这个变量是一个标志位,用来记录foo变量是否已经被初始化过了private volatile boolean bitmap$0;public static void main(String[] paramArrayOfString){LazyInitDemoForDecompilation..MODULE$.main(paramArrayOfString);}
}

在object中执行:

package cc11001100.scala.lazyStudy;import scala.Predef.;public final class LazyInitDemoForDecompilation$
{public static  MODULE$;static{new ();}public void main(String[] args){LazyInitDemoForDecompilation o = new LazyInitDemoForDecompilation();// 会将对变量的访问替换成调用访问器,// 这样的话编译器就可以很鸡贼的在访问器方法中插入各种处理以提供N多的语法糖,挺机智的Predef..MODULE$.println(o.foo());Predef..MODULE$.println(o.bar());}private LazyInitDemoForDecompilation$(){MODULE$ = this;}
}

综上源码,得出结论,scala的lazy关键字就是编译器在编译期将变量的初始化过程替换为Double Check Lock,类似于Java中的懒汉式单例模式初始化。

Scala同样使用了Java中常用的懒加载的方式自动帮助我们实现了延迟加载,并且还加锁避免多个线程同时调用初始化方法可能导致的不一致问题。

对于这样一个表达式: lazy val t:T = expr 无论expr是什么东西,字面量也好,方法调用也好。Scala的编译器都会把这个expr包在一个方法中,并且生成一个flag来决定只在t第一次被访问时才调用该方法。

http://www.yayakq.cn/news/251046/

相关文章:

  • 网站制作推广招聘医疗器械网站素材
  • 网站放视频代码php网站建立教程
  • 专门看广告的网站郑州市网络公司
  • 网站做电商资质吗挂机宝做php网站吗
  • 搭建网站需要注意什么怎么才能注册网站
  • 在国外做盗版电影网站吗做网站怎样办营业执照
  • 商城网站建设公司东莞网站建设专业品牌
  • 微网站建设服务建网站公司成都
  • 合肥做网站价格腾讯邮箱网页版登录入口
  • 怎么样管理网站wordpress 页面瀑布流
  • 极速建站太湖县城乡建设局网站
  • 中国百科网vip钓鱼网站开发灵犀科技 高端网站建设
  • 网站建设宽度一般都是多少钱wordpress 增加icon
  • 有没有做定制衣服的网站中山自助建站系统
  • 做网站订金为什么需要交那么多潍坊网站建设服务商
  • 福田市网站建设推广优秀学习网站
  • 怎么查询网站ftp地址n怎样建立自己的网站
  • 大连网站建设讯息信息服务平台
  • 自己做的网站上传到东莞凤岗网站建设
  • 外贸建站软件上海市建设小学网站
  • 湛江市seo网站设计报价汽车网站设计
  • 优秀网站设计欣赏图片搭建企业网站流程
  • 如何做adsense网站策划公司名称大全集最新
  • 论坛类网站备案代理加盟项目
  • 宁阳网站seo推广软件工程培训
  • 福建亨立建设集团有限公司网站小程序制作卡片列表
  • 几千元的网站建设强大的wordpress插件
  • 网站配色方案许昌建网站的公司在哪条路
  • 网站开发常见问题总结大型电子商务系统网站建设
  • ai网站百度浏览器