Почему `val` внутри` object` не является финальным автоматически?

В чем причинаvalне является (?) автоматически финальным в одноэлементных объектах? Например.

object NonFinal {
   val a = 0
   val b = 1

   def test(i: Int) = (i: @annotation.switch) match {
      case `a` => true
      case `b` => false
   }
}

результаты в:

:12: error: could not emit switch for @switch annotated match
          def test(i: Int) = (i: @annotation.switch) match {
                                                     ^

В то время как

object Final {
   final val a = 0
   final val b = 1

   def test(i: Int) = (i: @annotation.switch) match {
      case `a` => true
      case `b` => false
   }
}

Компилируется без предупреждений, поэтому, вероятно, генерирует более быструю таблицу сопоставления с образцом.

Нужно добавитьfinal мне кажется чистый раздражающий шум Isn»тobject Само по себе окончательное, а значит и его участники?

 drstevens24 янв. 2014 г., 21:46
Вы должны изменить принятый ответ на @extempore 'с (Пол Филлипс). В этом случае,final заставляет значение быть встроенным во время компиляции.
 Tony K.07 сент. 2012 г., 02:10
Согласовано. Я относительно новичок в Скале ... пытался исследовать возможные пути, о которых вы не думали.
 0__07 сент. 2012 г., 01:27
@TonyK. - что вы имеете в виду? Даже если бы яtrait T { def a: Int }объект переопределитa в правилах линеаризации. Если бы у меня былоtrait T { def a: Int = 33 }хорошо в этом случаеoverride final val это невозможно. Но я думаю, что это все еще нет дисквалифицировать подход созданиябез наиважнейшая vals final по умолчанию.
 Tony K.07 сент. 2012 г., 00:28
Гектометр как насчет черт, которые могут быть использованы?

Ответы на вопрос(3)

я думаю, что этот пункт из спецификации более актуален:

Определение константного значения имеет вид final val x = e, где e - постоянное выражение (§6,24). Окончательный модификатор должен присутствовать, и никакая аннотация типа не может быть дана. Ссылки на постоянное значение x сами по себе рассматриваются как константные выражения; в сгенерированном коде они заменяются определениемс правой стороны е.

По значимости:

Никакая аннотация типа не может быть данаВыражение e используется в сгенерированном коде (по моим прочтениям, в качестве исходного неоцененного константного выражения)

Для меня это звучит так, как будто спецификация требует, чтобы компилятор использовал эти больше как замены макросов, а не значения, которые оцениваются на месте во время компиляции, что может повлиять на работу результирующего кода.

Я думаю, что это особенно интересно, что аннотации типов не могут быть даны.

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

не спрашиватьпочему нет они финал ", вы'переспрашиваюпочему неТ они встроены. " Просто так получается, что final - это то, как вы указываете компилятору, что вы хотите, чтобы он был встроен.

Причина, по которой они не включаются автоматически, заключается в отдельной компиляции.

object A { final val x = 55 }
object B { def f = A.x }

Когда вы компилируете это, B.f возвращает 55, буквально:

public int f();
  0: bipush        55
  2: ireturn       

Это означает, что если вы перекомпилируете A, B не заметит изменения. Если x не помечен как финальный в A, B.f выглядит следующим образом:

  0: getstatic     #19                 // Field A$.MODULE$:LA$;
  3: invokevirtual #22                 // Method A$.x:()I
  6: ireturn       

Кроме того, чтобы исправить один из других ответов, окончательный не означает неизменяемый в Scala.

 psp20 сент. 2012 г., 11:57
финал также не означает константу. Пытаться "окончательный вариант х = 1; х = 2 ".
 fredoverflow01 июл. 2017 г., 15:47
похоже, это должен быть принятый ответ
Решение Вопроса

спецификацияи они автоматически становятся окончательными:

Члены конечных классов или объектов неявно также являются окончательными, поэтомуfinal модификатор, как правило, для них тоже избыточен. Обратите внимание, однако, что определения постоянных значений (§4.1) требуют явногоfinal модификатор, даже если они определены в конечном классе или объекте.

ВашfinalПример без компиляции без ошибок (или предупреждений) с 2.10-M7, поэтому яя предполагаю, чтопроблема с@switch проверка в более ранних версиях, и что члены на самом деле являются окончательными.

Обновление: На самом деле это более любопытно, чем я ожидал.если мы скомпилируем следующее с помощью 2.9.2 или 2.10-M7:

object NonFinal {
  val a = 0
}

object Final {
  final val a = 0
}

javap действительно показывает разницу:

public final class NonFinal$ implements scala.ScalaObject {
  public static final NonFinal$ MODULE$;
  public static {};
  public int a();
}

public final class Final$ implements scala.ScalaObject {
  public static final Final$ MODULE$;
  public static {};
  public final int a();
}

Вы видите то же самое, даже если правая часть определений значений не являетсят постоянное выражение.

Так что я'оставлю мой ответ, но этоне окончательно.

 Travis Brown07 сент. 2012 г., 00:48
@RexKerr: Действительно. Я нене помню, чтобы видел это в любом из журналов изменений, но япроверю еще раз.
 0__07 сент. 2012 г., 01:44
Да, я читал это так, хотя яне согласен со спецификацией здесь. Как я уже сказал, я думаю, что этос ненужным шумом.
 0__07 сент. 2012 г., 01:31
Спасибо, что спецификация довольно ясна, говоряvals нужно явноfinal, Странно, что 2.10.0-M7, возможно, стоит проверить полученный код соответствия шаблона (возможно,@switch молча уронили?)
 som-snytt03 июл. 2017 г., 06:48
Добавьте случай, чтобы увидеть предупреждение в 2.10+. Теперь документ говорит: Примечание: для совпадений с одним или двумя случаями компилятор генерирует инструкции перехода. Аннотирование такого совпадения с помощью @switch не выдает никаких предупреждений.
 Travis Brown07 сент. 2012 г., 01:38
@ 0__: Вы читаете, что требуется модификатор? Я'Я просто смущен этим сейчас, но интерпретировал бы это как высказывание, по крайней мере, что если бынет никаких шансов на определение постоянного значения (например, мыу нас есть"0".toInt или жеnew A на правой стороне), тоfinal избыточно
 Rex Kerr07 сент. 2012 г., 00:41
Я думал, что вы можете включить только постоянные значения, в этом случае 2.10-M7 снял требованиеfinal что ты цитировал. Нет?
 Rick-77709 сент. 2012 г., 00:25
То, что листинг javap показывает разницу, может не иметь значения. Насколько я помню из Java, финальный класс подразумевает и окончательность всех его полей и методов. Следовательно, что касается компилятора, желающего выполнить оптимизацию, он имеет ту же информацию, поэтому он должен иметь возможность выполнять те же оптимизации. Будет ли это так или нет, будет зависеть от того, насколько хорошо реализован этот бит компилятора.

Ваш ответ на вопрос