【发布时间】:2012-11-04 22:19:36
【问题描述】:
我以前认为private val 和private final val 是一样的,直到我在Scala Reference 中看到了第4.1 节:
常量值定义的格式为
final val x = e其中 e 是一个常量表达式(第 6.24 节)。 final 修饰符必须存在,并且不能给出类型注释。对常量值 x 的引用本身被视为常量表达式;在生成的代码中,它们被定义的右侧 e 替换。
我已经写了一个测试:
class PrivateVal {
private val privateVal = 0
def testPrivateVal = privateVal
private final val privateFinalVal = 1
def testPrivateFinalVal = privateFinalVal
}
javap -c 输出:
Compiled from "PrivateVal.scala"
public class PrivateVal {
public int testPrivateVal();
Code:
0: aload_0
1: invokespecial #19 // Method privateVal:()I
4: ireturn
public int testPrivateFinalVal();
Code:
0: iconst_1
1: ireturn
public PrivateVal();
Code:
0: aload_0
1: invokespecial #24 // Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_0
6: putfield #14 // Field privateVal:I
9: return
}
字节码正如Scala Reference所说:private val is not private final val。
scalac 为什么不将private val 视为private final val?有什么根本原因吗?
【问题讨论】:
-
换句话说:既然
val已经是不可变的,为什么我们在Scala 中还需要final关键字呢?为什么编译器不能像对待final vals 一样对待所有vals? -
请注意,
private作用域修饰符与 Java 中的package private具有相同的语义。你可能想说private[this]。 -
@ConnorDoyle:作为包私有?我不这么认为:
private的意思是它只对这个类的实例可见,private[this]只有这个实例——除了同一个类的实例,private不允许任何人(包括来自同一个包)来访问该值。