Разница между конечными переменными и постоянной времени компиляции
В чем разница между конечными переменными и константами времени компиляции?
Рассмотрим следующий код
final int a = 5;
final int b;
b=6;
int x=0;
switch(x)
{
case a: //no error
case b: //compiler error
}
Что это значит? Когда и как конечным переменным присваивается значение? Что происходит во время выполнения и что происходит во время компиляции? Почему мы должны дать переключателю постоянную времени компиляции? Какие другие структуры Java требуют постоянной времени компиляции?
5 ответов
Проблема в том, что все case:
заявления должны быть окончательными во время компиляции. Ваше первое утверждение является окончательным. a
не будет на 100% никакой другой ценности, кроме 5
,
final int a = 5;
Однако это не гарантируется для b
, Что делать, если вокруг будет if-заявление? b
?
final int b;
if(something())
b=6;
else
b=5;
Что это значит?
Это означает, что "b" не является константным выражением времени компиляции, и JLS требует, чтобы оно было.
Когда и как конечным переменным присваивается значение?
Формально, когда выполняется оператор присваивания или инициализатор.
Но на практике, если final
объявляет постоянную времени компиляции, выражение вычисляется во время компиляции, и его значение встроено в код.
Что происходит во время выполнения и что происходит во время компиляции?
Смотри выше.
Почему мы должны дать переключателю постоянную времени компиляции?
Потому что JLS требует этого.
Компилятору байт-кода необходимо проверить, что оператор switch правильно сформирован; то есть, что значения констант переключения не сталкиваются. Это также позволяет компилятору JIT генерировать код, оптимизированный для фактических значений констант коммутатора.
Какие другие структуры Java требуют постоянной времени компиляции?
Ничего такого, о чём я могу думать, вне головы.
С точки зрения компилятора вы пытаетесь использовать переменную b, которая не может быть инициализирована. Оператор switch скомпилирован в табличный переключатель или байт-код JVM, который требует, чтобы значения, используемые в операторе case, были как постоянной времени компиляции, так и уникальными.
final int a = 4; // compiler is sure a is initialized
final int b;// variable b is not guranted to be assigned
Например, хотя это утверждение в конечном итоге инициализирует b, но компилятор не может его обнаружить.
if (a < 4) b= 10;
if (a >= 4) b = 8
final int b;
может быть назначен один раз, и значение не уверен, что будет решено во время выполнения в зависимости от условий. По этой причине, даже если она является конечной переменной, она не является константой ВРЕМЕНИ ВРЕМЕНИ, хотя она будет константой ВРЕМЕНИ РАБОТЫ, и для случая требуются константы времени компиляции.
Оператору switch нужна константа. Поскольку конечные переменные могут быть отложены, они инициализируются, и компилятор не может определить для b, что он имеет значение в ветви case.