scala - 为什么 `private val` 和 `private final val` 不同?

标签 scala private final

我曾经认为 private valprivate final val 是相同的,直到我看到 Scala Reference 中的第 4.1 节:

A constant value definition is of the form

final val x = e

where e is a constant expression (§6.24). The final modifier must be present and no type annotation may be given. References to the constant value x are themselves treated as constant expressions; in the generated code they are replaced by the definition’s right-hand side 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 不是 private final val

为什么 scalac 不将 private val 视为 private final val?有什么根本原因吗?

最佳答案

所以,这只是一个猜测,但在 Java 中,右侧带有文字的最终静态变量会作为常量内联到字节码中,这是 Java 中长期存在的烦恼。这肯定会带来性能优势,但如果“常量”发生变化,则会导致定义的二进制兼容性破坏。当定义一个其值可能需要更改的最终静态变量时,Java 程序员必须采取一些技巧,例如使用方法或构造函数初始化该值。

Scala 中的 val 在 Java 意义上已经是最终的。看起来 Scala 的设计者正在使用冗余修饰符 Final 来表示“内联常量值的权限”。因此,Scala 程序员可以完全控制这种行为,而无需求助于 hack:如果他们想要一个内联常量,一个永远不会改变但速度很快的值,他们会编写“final val”。如果他们想要灵活地更改值而不破坏二进制兼容性,只需“val”。

关于scala - 为什么 `private val` 和 `private final val` 不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13412386/

相关文章:

regex - 在 Scala 中匹配 IP 地址

ruby - 是否可以比较 Ruby 中的私有(private)属性?

java - 类方法如何访问同一类的另一个实例的私有(private)成员?

C++ 设置私有(private)数组的值

java - HashMap 类中的 final方法

scala - 使用 Akka Streams 2.4.2 和 Slick 3.0 从 postgres 读取

json - 如何使用 json4s 从 akka-http 响应实体读取 json 响应

java - 为什么应该在所有构造函数中显式初始化一个空白的最终变量?

java - 'final' 字段修饰符在不可变类中是多余的吗?

scala - 使用 Scala 在 Apache Spark 中将矩阵转换为 RowMatrix