Ответ 1
Я не смог найти точную причину этого в JLS, поэтому я прошел через байтовый код и обнаружил, что причина в том, что компилятор не смог встроить значение i
в второй случай, но в состоянии сделать это в первом случае.
Здесь код:
final int x = 90;
System.out.println(x);
final int i;
i = 90;
System.out.println(i);
Скомпилированный байт-код выглядит так:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: bipush 90
5: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
8: bipush 90
10: istore_2
11: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
14: iload_2
15: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
18: return
Итак, в первом случае (от 3 до 5) он использует значение 90
для печати, а во втором случае (от 8 до 15) он должен сохранить значение в переменной, а затем загрузить обратно на стек. Затем метод print
будет выбирать верхнее значение стека.
Итак, в случае назначения:
byte x = i;
Значение i
будет выбрано из стека во время выполнения и не будет включено в компилятор. Поэтому компилятор не знает, какое значение может иметь значение i
.
Конечно, это все мое предположение. Байт-код может отличаться для разных JVM. Но у меня есть сильная интуиция, что это может быть причиной.
Кроме того, JLS & sect; 4.12.4 может иметь значение здесь:
Переменная примитивного типа или типа String, которая является окончательной и инициализирована выражением константы времени компиляции (§15.28), называется постоянной переменной.
Так как во втором случае переменная не инициализируется константным выражением, но позже ей присваивается значение, она больше не является постоянной переменной.