如果lazy val
是类变量,则会question询问def foo[A](a: => A) = {
lazy val x: A = a
// return something that uses x
}
的实现。如何实现本地变量,例如
{{1}}
答案 0 :(得分:3)
在方法中使用延迟val的效率要低一些。原因是你实际上不能嵌套函数,所以名义上在堆栈上分配的惰性位实际上需要在堆上。所以你必须创建至少一个额外的对象,事实证明Scala实际上创建了两个。
class Baz{
def baz(i: => Int, b: Boolean) = {
lazy val j = i
if (b) j else 0
}
}
除其他事项外,变成
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
查看IntRef
和VolatileByteRef
的创建?这些代替了通常只是私人vars来处理懒惰的val。现在j$1
,为处理lazy val的检索和/或创建而创建的访问器方法,必须将这两个新创建的类作为参数(除了通过名称函数)。
因此,虽然底层的机制是相同的,但是实现细节是不同的,并且效率低于你已经有另一个类来坚持变量。