Почему допустимая статическая конечная переменная не разрешена в статическом блоке инициализации?
Случай 1
class Program {
static final int var;
static {
Program.var = 8; // Compilation error
}
public static void main(String[] args) {
int i;
i = Program.var;
System.out.println(Program.var);
}
}
Случай 2
class Program {
static final int var;
static {
var = 8; //OK
}
public static void main(String[] args) {
System.out.println(Program.var);
}
}
Почему Случай 1 вызывает ошибку компиляции?
Ответы
Ответ 1
JLS содержит ответ (обратите внимание на жирный оператор):
Аналогично, каждая пустая конечная переменная должна назначаться не более одного раза; он должен быть определенно неназначен, когда происходит присвоение ему. Такое присваивание определяется как встречающееся тогда и только тогда, когда в левой части оператора присваивания либо простое имя переменной (или для поля, его простое имя, квалифицированное этим) происходит. [§16]
Это означает, что при назначении статических конечных переменных должно использоваться "простое имя", т.е. имя var без каких-либо квалификаторов.
Ответ 2
По-видимому, это дешевый синтаксический трюк для ограничения определенного (un) анализа назначения внутри самого класса.
Если поле синтаксически квалифицировано с именем класса, код обычно находится в другом классе, где анализ не может быть достигнут.
В вашем примере этот трюк не работает. Другие примеры странности:
static class A
{
static final int a;
static
{
// System.out.println(a); // illegal
System.out.println(A.a); // compiles!
a = 1;
}
}
Если у них было больше ресурсов, они, вероятно, сделали бы более тонкое правило. Но теперь мы не можем изменить спецификацию.