Постоянная времени компиляции
Я понял, что такое правило постоянной времени компиляции из констант и переменных времени компиляции.
- объявлен окончательным
- иметь примитивный или строковый тип
- инициализируется одновременно с объявлением
- инициализируется с постоянным выражением
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).
Если переменная объявлена без инициализации, она по определению не является константной переменной, даже если значение, которое вы в конечном итоге назначаете ей, является константным выражением.