变量和val的Scala内部

时间:2014-03-06 17:23:23

标签: scala

Scala中var和val的内部实现是什么?有兴趣知道他们的实现的细节 - 是什么使var变为“var”如何实现可变结构与val(更像是最终的)结构,这使得它不可变。

2 个答案:

答案 0 :(得分:12)

我将通过示例回答,使用scalacjavap

首先我创建Test.scala

class Test {
  val x = 1
  var y = 2
}

通过scalac Test.scala进行编译以生成Test.class,然后使用javap -p Test.class获取

public class Test {
  private final int x;
  private int y;
  public int x();
  public int y();
  public void y_$eq(int);
  public Test();
}

因此,您可以看到val x成为该类的private final字段,还有一个public final方法可以返回该值。

var y成为一个非最终的私人领域,以及一个getter + setter对。 y_$eq(int)是设定者。在scala中,那将是def y_=(newY: Int): Unit。 Scala的语法糖会将y = someValue转换为对y_=(someValue)的调用。

答案 1 :(得分:4)

您必须区分声明(在类模板中)与定义(在块中,或在模板中声明成员并构成构造函数体)

4.2节中指定var decl等同于getter / setter对。

作为实施细节,val只是一个吸气剂。

两个成员都有一个私有支持字段,名称略有损坏:它有一个尾随空格。

有一些异常现象,例如:

scala> class X { final val x = 7 }  // the underlying field is not initialized
defined class X

scala> :javap -prv X
{
[snip]
  private final int x;
    flags: ACC_PRIVATE, ACC_FINAL
[snip]
  public $line5.$read$$iw$$iw$X();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0       
         1: invokespecial #14                 // Method java/lang/Object."<init>":()V
         4: return        

模板和块之间的材料差异:

scala> class Y { def y = { var z = 0; def z_=(zz: Int): Unit = ???; z = 1; z } }

scala> class Y { var z = 0; def z_=(zz: Int): Unit = ???; z = 1 }
<console>:7: error: method z_= is defined twice

在REPL中,你真的在​​制作模板(因为所有内容都包含在一个类中):

scala> var z = 0 ; def z_=(zz: Int): Unit = ???
<console>:7: error: method z_= is defined twice
  conflicting symbols both originated in file '<console>'
       var z = 0 ; def z_=(zz: Int): Unit = ???
                       ^

scala> { var z = 0 ; def z_=(zz: Int): Unit = ??? }