1. ホーム
  2. scala

[解決済み] なぜ `private val` と `private final val` は違うのですか?

2022-12-27 22:07:24

疑問点

私は以前、次のように考えていました。 private valprivate final val が同じであることを確認しました。

定数値の定義は、以下のような形式です。

final val x = e

ここで、eは定数式である(6.24節)。最終修飾子が存在しなければならず、型注釈は与えてはならない。定数値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 valprivate final val .

なぜ スカラ は単に private val として private final val ? 何か根本的な理由があるのでしょうか?

どのように解決するのですか?

これは単なる推測ですが、右辺にリテラルを持つ最後の静的変数が定数としてバイトコードにインライン化されることは、Java における長年の悩みの種でした。これは確かにパフォーマンス上の利点がありますが、定数が変更された場合、定義のバイナリ互換性が損なわれてしまいます。値が変更される可能性のある最終的な静的変数を定義する場合、Java プログラマーは、メソッドまたはコンストラクターで値を初期化するなどのハックに頼らなければなりません。

Scalaのvalは、Javaの意味においてすでにfinalです。Scalaの設計者は、冗長な修飾子finalを使って、定数値をインライン化する許可"を意味しているように見えます。つまり、Scalaプログラマはハックに頼ることなく、この動作を完全に制御することができます。もし、インライン定数、つまり決して変化してはならないが高速な値が欲しければ、 "final val" と書きます。もし、バイナリ互換性を破壊せずに値を柔軟に変化させたい場合は "val" だけです。