scala:为什么下划线(_)初始化对字段而不是方法变量起作用?

Itt*_*ayD 12 scala

这工作:

scala> class foo[T] {
     | var t: T = _
     | }
defined class foo
Run Code Online (Sandbox Code Playgroud)

但这不是:

scala> def foo[T] = {
     |   var t: T = _
     | }
<console>:5: error: local variables must be initialized
         var t: T = _
Run Code Online (Sandbox Code Playgroud)

为什么?

(可以使用:

var t: T = null.asInstanceOf[T]
Run Code Online (Sandbox Code Playgroud)

)

oxb*_*kes 8

这在Scala语言规范的4.2节中定义(我的斜体)

变量定义只能作为模板的成员var x: T = _出现.它引入了一个带有类型和默认初始值的可变字段T

当然,这并没有回答为什么会这样!

  • 那为什么会这样呢? (4认同)

che*_*hes 8

一个邮件列表线程马丁回答:

它对应于JVM.您可以省略字段初始化,但不能省略局部变量初始化.省略局部变量初始化意味着编译器必须能够为每种类型合成默认值.面对类型参数,专业化等等,这并不容易.

当关于Scala合成默认值时字段和本地之间是否存在或应该有任何区别时,他继续说:

就字节码而言,存在明显的差异.JVM将默认初始化对象字段,并要求显式初始化局部变量.[...]我不确定我们是否应该打破一个有用的Java原则(本地人必须在使用之前进行初始化),或者我们是否应该全力以赴并引入基于流的初始化检查,就像在Java中一样.这将是更好的解决方案,IMO,但在规范和实施方面需要大量工作.面对这些选择,我的本能就是现在什么都不做:-)

因此,如果我理解正确,Scala编译器实际上并不合成对象字段的默认值,它会生成字节码,让JVM处理这个问题.

根据SI-4437,马丁已经同意实际支持null.asInstanceOf[T]语言规范中的模式,似乎是因为缺乏能够在现有约束条件下切实支持更好的替代方案.