Я понял, что такое правило постоянной времени компиляции из Константы и переменные времени компиляции.
final int x = 5;
Но я не понимаю, почему код ниже:
final int x;
x = 5;
Единственное отличие состоит в третьем пункте выше. Как инициализация на другой строке вместо той же имеет значение.
Я думаю, что они также стремились к не слишком сложному набору правил. Я не могу представить себе управляемое правило, которое охватывало бы ваш второй фрагмент, не создавая проблем где-либо еще. Где провести предел?
Я голосую за то, чтобы закрыть этот вопрос как не по теме, потому что ответы могут быть только предположениями (и в лучшем случае чтением мыслей),
запустите код final int a = 1; final int b; b = 2; switch (1) {case a: // OK case b: // ошибка компиляции
Если какие-либо переменные объявлены как final, это означает, что они могут инициализироваться только один раз, и это должно произойти во время объявления @Nizam




Дело 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 никогда не может быть переназначен, конечно, потому что они объявлены final. Разница (как видно по байт-коду) в том, что в первом случае значение x заменяет во время компиляции каждую ссылку на x.
A constant variable is a final variable of primitive type or type String that is initialized with a constant expression (§15.28).
Если переменная объявлена без инициализации, она по определению не является постоянной переменной, даже если значение, которое вы ей в конечном итоге присваиваете, является постоянным выражением.
Вы можете получить ошибку времени компиляции, когда эти две строки разделены каким-либо другим оператором, пытающимся получить доступ к
x. В противном случае не уверены, что вам не подходит!