当我们在 java 中创建一个 final 时,它保证即使在运行时也不能更改,因为 JVM 保证了这一点。
Java 类:
public class JustATest {
public final int x = 10;
}
Javap反编译:
编译自“JustATest.java”
public class JustATest {
public final int x;
public JustATest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 10
7: putfield #2 // Field x:I
10: return
}
但在 scala 中,如果我们声明一个 val
,它会编译成一个普通的整数,并且在反编译输出方面 var 和 val 没有区别。
原始 Scala 类:
class AnTest {
val x = 1
var y = 2
}
反编译输出:
Compiled from "AnTest.scala"
public class AnTest {
public int x();
Code:
0: aload_0
1: getfield #14 // Field x:I
4: ireturn
public int y();
Code:
0: aload_0
1: getfield #18 // Field y:I
4: ireturn
public void y_$eq(int);
Code:
0: aload_0
1: iload_1
2: putfield #18 // Field y:I
5: return
public AnTest();
Code:
0: aload_0
1: invokespecial #25 // Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_1
6: putfield #14 // Field x:I
9: aload_0
10: iconst_2
11: putfield #18 // Field y:I
14: return
}
根据这些信息,val
的不变性概念仅在编译时由 scala 编译器控制?这在运行时如何保证?
最佳答案
在 Scala 中,通过 val
传递不变性是一种编译时执行,它与发出的字节代码无关。在 Java 中,您声明当字段为 final
时,为了不对其进行重新分配,而在 Scala 中,使用 val
声明变量仅意味着它不能被重新分配重新分配,但它可以被覆盖。如果您希望一个字段是final
,您需要像在 Java 中那样指定它:
class AnTest {
final val x = 10
}
产生:
public class testing.ReadingFile$AnTest$1 {
private final int x;
public final int x();
Code:
0: bipush 10
2: ireturn
public testing.ReadingFile$AnTest$1();
Code:
0: aload_0
1: invokespecial #19 // Method java/lang/Object."<init>":()V
4: return
}
这等同于您在 Java 中看到的字节码,只是编译器为 x
发出了一个 getter。
关于java - Scala - 如何在运行时保证 val 不变性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39893661/