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

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

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

final int x = 5;

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

final int x;
x = 5;

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

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

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

На самом деле, в идеале, таком как 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

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

Из JLS Sec 4.12.4:

Постоянная переменная - это конечная переменная примитивного типа или типа String, которая инициализируется постоянным выражением (§15.28).

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

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