gil*_*och 5 scala lazy-evaluation
我在扩展的对象中遇到了一些bizzar行为App.看看以下REPL命令:
scala> object A extends App {val x = "I am null"}
defined module A
scala> object B {val x = "I am a string"}
defined module B
scala> A.x
res0: java.lang.String = null
scala> B.x
res1: java.lang.String = I am a string
Run Code Online (Sandbox Code Playgroud)
好吧,这有点奇怪......但它变得更加怪异.然后我认为vals object进入一些懒惰的评估...所以我尝试了一个真实的lazy val:
scala> object C extends App {lazy val x = "What am I?"}
defined module C
scala> C.x
res2: java.lang.String = What am I?
Run Code Online (Sandbox Code Playgroud)
那么这里发生了什么?为什么常规val获得空值?
当我使用时,为什么这种行为会改变lazy val?
这个App特质有什么特别之处,这使得常规价值得不到评估?
App扩展了DelayedInit特性.因此,所有语句和所有值定义都将移至delayedInit方法.Lazy val可以工作,因为它编译为方法.
例如,如果您反编译此类:
class TestApp extends App{
val test = "I am null"
lazy val testLazy ="I am a string"
}
Run Code Online (Sandbox Code Playgroud)
您将使用'懒惰方法'获得课程:
public String testLazy()
{
if((bitmap$0 & 1) == 0)
synchronized(this)
{
if((bitmap$0 & 1) == 0)
{
testLazy = "I am a string";
bitmap$0 = bitmap$0 | 1;
}
BoxedUnit _tmp = BoxedUnit.UNIT;
}
return testLazy;
}
Run Code Online (Sandbox Code Playgroud)
和内部类中的delayedInit方法 delayedInit.body:
public final class delayedInit.body extends AbstractFunction0
implements ScalaObject
{
public final Object apply()
{
$outer.test_$eq("I am null");
return BoxedUnit.UNIT;
}
private final TestApp $outer;
....
Run Code Online (Sandbox Code Playgroud)
因此,test只有在调用delayedInit时,才会将值"I is null"分配给字段.