gpt4 book ai didi

c# - 为什么 .NET 的 Scala 编译器会忽略 val 的含义?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:23:10 25 4
gpt4 key购买 nike

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

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

class HowAreVarAndValImplementedInScala {
var v1 = 123
val v2 = 456

def method1() = {
var v3 = 123
val v4 = 456
println(v3 + v4)
}
}

如果我将上面的 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));
}
}

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

2 scala compiler for .net adds override keyword to lot of (if not all) public instance methods

如果我们把上面展示的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;
}
}

所有公共(public)实例方法(不包括构造函数)都被标记为重写,为什么?有必要吗?

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

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

最佳答案

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

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

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

CIL 等同于 Java 的 final 字段标志是 initonly,它似乎具有相同的语义。不清楚为什么 Scala 编译器不发出这个。也许他们只是没有抽出时间来解决这个问题?或者您使用的 .net 反编译器可能没有反射(reflect)这一点。如果您想查看编译器实际生成的内容,最好直接查看字节码。

关于c# - 为什么 .NET 的 Scala 编译器会忽略 val 的含义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16443524/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com