Scala的本地惰性变量是如何实现的?

Pet*_*lák 5 scala local-variables lazy-evaluation scala-2.10

如果它们是类变量,那么有一个问题询问lazy vals 的实现.如何实现局部变量,例如

def foo[A](a: => A) = {
  lazy val x: A = a
  // return something that uses x
}
Run Code Online (Sandbox Code Playgroud)

Rex*_*err 3

在方法中使用惰性值的效率有点低。原因是您实际上无法嵌套函数,因此名义上在堆栈上分配的惰性位实际上需要在堆上分配。所以你必须至少创建一个额外的对象,而事实证明 Scala 实际上创建了两个。

class Baz{
  def baz(i: => Int, b: Boolean) = {
    lazy val j = i
    if (b) j else 0
  }
}
Run Code Online (Sandbox Code Playgroud)

除其他外,变成

public int baz(scala.Function0, boolean);
  Code:
   0:   new #12; //class scala/runtime/IntRef
   3:   dup
   4:   iconst_0
   5:   invokespecial   #16; //Method scala/runtime/IntRef."<init>":(I)V
   8:   astore_3
   9:   new #18; //class scala/runtime/VolatileByteRef
   12:  dup
   13:  iconst_0
   14:  invokespecial   #21; //Method scala/runtime/VolatileByteRef."<init>":(B)V
   17:  astore  4
   19:  iload_2
   20:  ifeq    34
   23:  aload_0
   24:  aload_1
   25:  aload_3
   26:  aload   4
   28:  invokespecial   #25; //Method j$1:(Lscala/Function0;Lscala/runtime/IntRef;
                                               Lscala/runtime/VolatileByteRef;)I
   31:  goto    35
   34:  iconst_0
   35:  ireturn
Run Code Online (Sandbox Code Playgroud)

IntRef看到和的创建了VolatileByteRef吗?这些代替了通常只是处理惰性 val 的私有变量。现在j$1,为处理惰性 val 的检索和/或创建而创建的访问器方法必须将这两个新创建的类作为参数(除了按名称函数之外)。

因此,虽然底层机制是相同的,但实现细节是不同的,并且与您已经有另一个类来粘贴变量相比效率较低。