5

我在扩展的对象中遇到了一些奇怪的行为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

嗯,这有点奇怪……但它变得更奇怪了。然后我认为 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?

那么这里发生了什么?为什么常规 val 得到一个空值?
为什么我使用时这种行为会发生变化lazy val
该特征有什么特别之处App,使常规 vals 不被评估?

4

1 回答 1

9

App 扩展了 DelayedInit特征。因此,所有语句和所有值定义都移至delayedInit方法。Lazy val 之所以有效,是因为它编译为方法。

例如,如果你反编译这个类:

class TestApp extends App{
  val test = "I am null"
  lazy val testLazy ="I am a string"
}

您将使用“惰性方法”上课:

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;
} 

和内部类中的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;
....

test因此,只有在调用延迟初始化时,才会将值“我为空”分配给字段。

于 2012-10-22T10:27:01.273 回答