Подтвердить что ты не робот

Почему допустимая статическая конечная переменная не разрешена в статическом блоке инициализации?

Случай 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 вызывает ошибку компиляции?

4b9b3361

Ответ 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;
    }
}

Если у них было больше ресурсов, они, вероятно, сделали бы более тонкое правило. Но теперь мы не можем изменить спецификацию.