jde*_*lop 21 scala compilation reference
可能重复:
Scala:转发引用 - 为什么这段代码会编译?
object Omg {
class A
class B(val a: A)
private val b = new B(a)
private val a = new A
def main(args: Array[String]) {
println(b.a)
}
}
Run Code Online (Sandbox Code Playgroud)
以下代码打印"null".在java中.由于前向引用无效,类似的构造无法编译.问题是 - 为什么它在Scala中编译得很好?这是设计,在SLS中描述还是仅仅是2.9.1中的错误?
par*_*tic 28
这不是一个bug,而是学习Scala时的一个经典错误.Omg初始化对象时,首先将所有值设置为默认值(null在本例中),然后运行构造函数(即对象主体).
要使其工作,只需lazy在您正在引用的声明前添加关键字(a在本例中为值):
object Omg {
class A
class B(val a: A)
private val b = new B(a)
private lazy val a = new A
def main(args: Array[String]) {
println(b.a)
}
}
Run Code Online (Sandbox Code Playgroud)
a然后根据需要初始化价值.
这种结构很快(值只对所有应用程序运行时初始化一次)和线程安全.
我理解它的方式,这与Scala类的创建方式有关.在Java中,上面定义的类将内联初始化变量,并且由于a尚未定义,因此无法编译.但是,在Scala中,它在Java中更相当于它(在同一场景中也应该生成null):
class Omg {
private B b = null;
private A a = null;
Omg(){
b = new B(a);
a = new A();
}
}
Run Code Online (Sandbox Code Playgroud)
或者,你可以使你的b延迟声明,这将推迟设置值直到它被调用(此时将设置一个).
如果这是一个问题,请-Xcheckinit在开发期间进行编译并迭代,直到异常消失为止.
规范5.1按顺序执行的模板体语句; 4.0的开头,用于块中的前向引用.