Почему `частная Вэл` и `частная окончательной Валь-другому?


я раньше так думал private val и private final val такие же, пока я не увидел раздел 4.1 в Scala ссылка:

определение постоянного значения имеет вид

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 сказал: private val - это не private final val.

почему бы и нет scalac просто лечить private val как private final val? Есть ли подоплека?

2 94

2 ответа:

Итак, это всего лишь предположение, но это было постоянное раздражение в Java, что конечные статические переменные с литералом с правой стороны вставляются в байт-код в качестве констант. Это дает несомненное преимущество в производительности, но это приводит к тому, что двоичная совместимость определения нарушается, если "константа" когда-либо менялась. При определении конечной статической переменной, значение которой может потребоваться изменить, программисты Java должны прибегать к хакам, таким как инициализация значения с помощью метода или конструктор.

вал в Scala уже является окончательным в смысле Java. Похоже, что дизайнеры Scala используют избыточный модификатор final, чтобы означать "разрешение на встроенное постоянное значение". Таким образом, программисты Scala имеют полный контроль над этим поведением, не прибегая к хакам: если они хотят встроенную константу, значение, которое никогда не должно меняться, но быстро, они пишут "final val". если они хотят гибкость, чтобы изменить значение без нарушения бинарной совместимости, просто "вал."

valS может быть переопределен в дочерних классах, и поэтому не может рассматриваться как окончательное, если не обозначены явно.

@Brian REPL предоставляет область действия класса на уровне строки. Смотрите:

scala> $iw.getClass.getPackage
res0: Package = package $line3

scala> private val x = 5
<console>:5: error: value x cannot be accessed in object $iw
  lazy val $result = `x`

scala> private val x = 5; println(x);
5