为什么用于.NET的Scala编译器忽略了val的含义?

Cui*_*崔鹏飞 7 c# java cil scala bytecode

我正在玩Scala.我发现了3个有趣的东西(标题是第三个).

1声明为val的局部变量不会被解释为final.

class HowAreVarAndValImplementedInScala {
  var v1 = 123
  val v2 = 456

  def method1() = {
    var v3 = 123
    val v4 = 456
    println(v3 + v4)
  }
}
Run Code Online (Sandbox Code Playgroud)

如果我将上面的scala代码编译成字节码,然后将其反编译成java,它看起来像这样:

public class HowAreVarAndValImplementedInScala
{
  private int v1 = 123;
  private final int v2 = 456;

  public int v1()
  {
    return this.v1;
  }

  public void v1_$eq(int x$1) { this.v1 = x$1; }

  public int v2() { return this.v2; }

  public void method1() {
    int v3 = 123;
    int v4 = 456;
    Predef..MODULE$.println(BoxesRunTime.boxToInteger(v3 + v4));
  }
}
Run Code Online (Sandbox Code Playgroud)

我们可以看到v2是最终的,但v4不是,为什么?

.net的2个scala编译器将override关键字添加到许多(如果不是全部)公共实例方法中

如果我们将上面显示的scala代码编译成CIL然后将其反编译成C#,它就像这样:

public class HowAreVarAndValImplementedInScala : ScalaObject
{
  private int v1;
  private int v2;

  public override int v1()
  {
    return this.v1;
  }

  public override void v1_$eq(int x$1)
  {
    this.v1 = x$1;
  }

  public override int v2()
  {
    return this.v2;
  }

  public override void method1()
  {
    int v3 = 123;
    int v4 = 456;
    Predef$.MODULE$.println(v3 + v4);
  }

  public HowAreVarAndValImplementedInScala()
  {
    this.v1 = 123;
    this.v2 = 456;
  }
}
Run Code Online (Sandbox Code Playgroud)

所有公共实例方法(排除构造函数)都标记为覆盖,为什么?那有必要吗?

3.用于.net的Scala编译器失去了val的含义

在上面的c#代码中,我们可以看到v2只是一个普通的字段,而在java couter部分,v2被标记为final,不应该由scala编译器为.net标记为只读v2(一个bug? )

Ant*_*ony 7

在字节码级别,对于局部变量,final不存在.事实上,局部变量的概念本身也不存在.将局部变量标记为final是纯粹用于编译时检查.由于类文件中不存在该信息,因此反编译器无法猜测它.

至于后两个问题,我对CIL字节码并不熟悉,但是如果我不得不猜测我没有理由不添加覆盖,并且readonly可能有不同的语义.

编辑:在查看CIL规范之后,这是我发现的内容.

CIL相当于Java的final字段标志initonly,它看起来具有相同的语义.目前尚不清楚为什么Scala编译器不会发出这个.也许他们只是没有绕过它?或许你使用的.net反编译器没有反映出这一点.如果你想看看编译器实际生成了什么,你最好直接查看字节码.

  • Scala.NET实际上并没有将Scala编译为CIL.它使用Scala的标准JVM实现将Scala编译为JVML,然后使用IKVM.NET将JVML编译为CIL.因此,字段未标记为"initonly"的原因可能是由于生成的`.class`文件中没有足够的信息供IKVM.NET推断. (5认同)