I’ve encountered a somewhat bizzar behavior in objects that extends App. take a look at the following REPL commands:
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
well, this is a bit weird… but it gets weirder. i then thought the vals in an object go into some lazy evaluation… so i tried a real 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?
so what’s happening here? why is a regular val gets a null value?
why does this behavior changes when i use lazy val?
and what is so special with the App trait, that makes the regular vals to be unevaluated?
App extends DelayedInit trait. So all statements and all value definitions are moved to
delayedInitmethod. Lazy val works because it compiles to method.For example if you decompile this class:
You will get class with ‘lazy method’:
and delayedInit method in inner class
delayedInit.body:So value “I am null” will be assigned to
testfield only when delayedInit is called.