美文网首页
scala lazy引发的疑问

scala lazy引发的疑问

作者: 吐思圈 | 来源:发表于2018-01-10 21:52 被阅读0次

by 十三

背景:
近日遇到个奇怪的问题:在没有明显循环或递归的代码地方,日志中却抛出了stackoverflow的错误,由于代码入口处是调用了configuration获取yarn的配置,所以刚开始定位思路有点跑偏了,后来就尝试去掉了lazy关键词,发现错误没有了,根据后续的日志打印发现,跟预期有出入,才发现是因为log中使用了错误的变量(看来是写代码太不走心了,走查代码也没走心,😢),至此才发现问题根因。

原因:
我们先来看如下两段代码的区别

片段1:

  lazy val upperLimit: Int = {
    val increment: Int = 512//最初是conf.getSomeValue方法,方便起见赋初值
    val containerMaxMem: Int = 20//最初是conf.getSomeValue方法,方便起见赋初值
    val upper = (containerMaxMem - math.ceil(math.max(containerMaxMem * 0.1 * 1024, 384)) / increment * increment / 1024.0).toInt
    log.debug(s"upper = $upperLimit")
    upper
  }

  println(upperLimit)

片段2:

val upperLimit: Int = {
    val increment: Int = 512
    val containerMaxMem: Int = 20
    val upper = (containerMaxMem - math.ceil(math.max(containerMaxMem * 0.1 * 1024, 384)) / increment * increment / 1024.0).toInt
    log.debug(s"upper = $upperLimit")
    upper
  }

  println(upperLimit)

从代码的角度来看,唯一的区别在于前者多了一个lazy,那么两段代码的输出会有什么差别吗?
我们来看看输出结果:
片段1的输出:

An exception or error caused a run to abort. 
java.lang.StackOverflowError
    at sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:691)
    at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:579)
    at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:271)
    at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:125)
    at java.io.OutputStreamWriter.write(OutputStreamWriter.java:207)
    at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:129)
    at java.io.PrintStream.write(PrintStream.java:526)
    at java.io.PrintStream.print(PrintStream.java:669)
    at java.io.PrintStream.println(PrintStream.java:823)
    at scala.Console$.println(Console.scala:148)
    at scala.Predef$.println(Predef.scala:315)

片段2的输出:

0
18

片段1中由于加了lazy关键词,所以在log中首次使用的时候,才会去真正计算它的值,在没有得到返回值之前,log中又开始计算值,所以不断地压栈,最终导致栈溢出的错误。
而片段2中,去掉了lazy关键词,log中首次使用的时候,就会使用Int类型的初始值,也就是0.

最后再看一看

scala> lazy val a = 1
a: Int = <lazy>

scala> a
res1: Int = 1

scala> val a = 1
a: Int = 1

lazy虽好,使用还得谨慎。

相关文章

  • scala lazy引发的疑问

    by 十三 背景:近日遇到个奇怪的问题:在没有明显循环或递归的代码地方,日志中却抛出了stackoverflow的...

  • Scala的For、Function、Lazy、Exceptio

    for循环,不论在哪个语言里面都是很基本的循环语句 遍历集合: 条件守卫: 函数的定义: 一般情况下,是不需要声明...

  • Scala中lazy val的用法

    lazy修饰变量就是为了延迟初始化 When a val is declared as lazy, its ini...

  • Scala关键字lazy的理解和使用

    Scala中使用关键字lazy来定义惰性变量,实现延迟加载(懒加载)。惰性变量只能是不可变变量,并且只有在调用惰性...

  • 丢手机引发的疑问

    现在智能手机的普及,大家应该都有丢手机的经历吧! 那大家来分享一下丢手机的惨痛教训吧! 1.由于比较低调,我不喜欢...

  • 看地图引发的疑问

    今天下午小屁孩回到我的办公室,看到悬挂的世界地图就问:为什么有三个图?是不是有三个地球? 我愣了一下就回答:只有一...

  • Lazy-Loading 引发的 dealloc 问题

    我们知道一个 ViewController 有着固定的 Load 顺序: 页面 Push 创建时 页面 Pop 返...

  • scala中如何实现的lazy变量的懒加载

    lazy关键字可以用来修饰不可变变量,该关键字的作用是:当对象被真正使用的时候才会被初始化。经常用于一些可能用到也...

  • 函数的语法

    函数 -> lazy_sum 函数调用 -> lazy_sum() 函数调用的结果 -> f = lazy_sum...

  • Kotlin的by lazy与lateinit区别

    1、by lazy 1.1、by lazy 惰性加载->用到的时候在加载的意思1.2 by lazy 知道具体值...

网友评论

      本文标题:scala lazy引发的疑问

      本文链接:https://www.haomeiwen.com/subject/lgagnxtx.html