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

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

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

final int x = 5;

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

final int x;
x = 5;

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

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

Naman 22.12.2018 18:08

Я думаю, что они также стремились к не слишком сложному набору правил. Я не могу представить себе управляемое правило, которое охватывало бы ваш второй фрагмент, не создавая проблем где-либо еще. Где провести предел?

Ole V.V. 22.12.2018 18:21

Я голосую за то, чтобы закрыть этот вопрос как не по теме, потому что ответы могут быть только предположениями (и в лучшем случае чтением мыслей),

Ole V.V. 22.12.2018 18:22

запустите код final int a = 1; final int b; b = 2; switch (1) {case a: // OK case b: // ошибка компиляции

Nizam 22.12.2018 18:26

Если какие-либо переменные объявлены как final, это означает, что они могут инициализироваться только один раз, и это должно произойти во время объявления @Nizam

Deadpool 22.12.2018 18:30
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
5
813
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Дело 1final 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

Случай 2final 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 строки case 2 с одной строкой, как case 1.

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

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

The JLS does not contain the phrase compile-time constant.
However, programmers often use the terms compile-time constant and constant interchangeably.

Теперь о том, как компилятор использует 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

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

Гораздо лучшее объяснение, но я заметил, что может быть небольшая разница в работе серверной части, но на передней части их поведение будет таким же, т.е. на консоли они оба напечатают 5 и никогда не могут быть переназначены. @ Forpas

Nizam 01.01.2019 12:54

@Nizam никогда не может быть переназначен, конечно, потому что они объявлены final. Разница (как видно по байт-коду) в том, что в первом случае значение x заменяет во время компиляции каждую ссылку на x.

forpas 01.01.2019 13:12

От JLS, раздел 4.12.4:

constant variable is a final variable of primitive type or type String that is initialized with a constant expression (§15.28).

Если переменная объявлена ​​без инициализации, она по определению не является постоянной переменной, даже если значение, которое вы ей в конечном итоге присваиваете, является постоянным выражением.

Другие вопросы по теме