Постоянная времени компиляции

Я понял, что такое правило константы времени компиляции, из констант и переменных времени компиляции.

  1. объявлен окончательным
  2. иметь примитивный или строковый тип
  3. инициализируется одновременно с объявлением
  4. инициализируется константным выражением

final int x = 5;

Но я не понимаю, почему ниже код не работает:

final int x;
x = 5;

Единственная разница заключается в третьем пункте выше. Как инициализация в другой строке вместо той же строки имеет значение.


person Nizam    schedule 22.12.2018    source источник
comment
Возможно, вы можете получить ошибку времени компиляции, когда эти две строки разделены каким-то другим оператором, пытающимся получить доступ к x. В противном случае не уверен, что не работает для вас!   -  person Naman    schedule 22.12.2018
comment
Я думаю, что они также стремились к не слишком сложному набору правил. Я не могу вообразить управляемое правило, которое охватило бы ваш второй фрагмент, не создавая проблем в другом месте. Где провести лимит?   -  person Ole V.V.    schedule 22.12.2018
comment
Я голосую за то, чтобы закрыть этот вопрос как не по теме, потому что ответы могут быть только догадками (и в лучшем случае чтением мыслей),   -  person Ole V.V.    schedule 22.12.2018
comment
запустите код final in a = 1; конечный интервал b; б = 2; switch(1) { case a : // OK case b : // ошибка компиляции   -  person Nizam    schedule 22.12.2018
comment
Если какие-либо переменные объявлены как final, это означает, что они могут инициализироваться только один раз, и это должно произойти во время объявления @Nizam   -  person Deadpool    schedule 22.12.2018


Ответы (2)


Случай 1 final int x = 5;

public static void main(String[] args) {
    final int x = 5;
}

Сгенерированный байт-код:

  public static main([Ljava/lang/String;)V
   L0
    LINENUMBER 3 L0
    ICONST_5
    ISTORE 1
   L1
    LINENUMBER 4 L1
    RETURN
   L2
    LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
    LOCALVARIABLE x I L1 L2 1
    MAXSTACK = 1
    MAXLOCALS = 2

Случай 2 final int x; x = 5;

public static void main(String[] args) {
    final int x;
    x = 5;
}

Сгенерированный байт-код:

  public static main([Ljava/lang/String;)V
   L0
    LINENUMBER 4 L0
    ICONST_5
    ISTORE 1
   L1
    LINENUMBER 5 L1
    RETURN
   L2
    LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
    LOCALVARIABLE x I L1 L2 1
    MAXSTACK = 1
    MAXLOCALS = 2

Как видите, между двумя случаями нет никакой разницы, кроме номеров строк.

На самом деле в ide, таком как InteliJ, вы увидите подсказку (в виде лампочки) соединить 2 строки случая 2 с 1 строкой, как случай 1.

Если вы прочитаете все ответы и комментарии по предоставленной вами ссылке,
вы скорее запутаетесь, чем поймете.
Все дело в терминологии, и в данном случае в недокументированной терминологии.

Это выдержка из одного из ответов по этой ссылке:

JLS не содержит константы времени компиляции фразы.
Однако программисты часто используют термины "константа времени компиляции" и "константа" как синонимы.

Теперь о том, как компилятор использует 2 случая.
Если вы добавите эту строку в конце обоих методов:

System.out.println(x);


сгенерированный байт-код:
для случай 1

GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ICONST_5
INVOKEVIRTUAL java/io/PrintStream.println (I)V

и для варианта 2

GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ILOAD 1
INVOKEVIRTUAL java/io/PrintStream.println (I)V

Во 2-м случае есть разница: ILOAD 1 вместо ICONST_5.
Значение в 1-м случае x было заменено на 5, а во 2-м случае не было и значение x было вызвано (загружено) для выполнения оператора .

person forpas    schedule 22.12.2018
comment
Гораздо лучшее объяснение, но я наблюдаю, что может быть небольшая разница в работе серверной части, но во внешнем интерфейсе их поведение будет одинаковым, то есть на консоли они оба будут печатать 5 и никогда не могут быть переназначены. @forpas - person Nizam; 01.01.2019
comment
@Nizam никогда нельзя переназначить, конечно, потому что они объявлены final. Разница (как видно из байт-кода) в том, что в первом случае значение x заменяет во время компиляции каждую ссылку на x. - person forpas; 01.01.2019