Ошибка статического инициализатора при размещении перед объявлением

Я заметил что-то в статических инициализаторах, которые могут быть ошибкой в javac. Я построил сценарий, в котором я могу назначить переменной значение, но не прочитать это значение обратно.

два примера ниже, первый компилируется нормально, второй получает ошибку при попытке прочитать значение из tmp, но по какой-то причине назначение значения tmp разрешено. Я мог бы понять, если бы он не мог ни читать, ни писать в переменную, так как tmp объявлен после статического инициализатор, но ошибка только на одном из них не имеет для меня смысла.

//Compiles Successfully:
public class Script
{
    public static Object tmp;
    static
    {
        tmp = new Object();
        System.out.println(tmp);
    }

}

//error only on the read but not the assignment
public class Script
{

    static
    {
        tmp = new Object();
        System.out.println(tmp);
    }
    public static Object tmp;
}

чтобы подчеркнуть этот момент дальше, это успешно компилируется.

public class Script
{

    static
    {
        tmp = new Object();
    }
    public static Object tmp;
}

1 ответов


кажется, это определено в спецификации (см. JLS 8.3.2.3):

объявление члена должно появиться текстуально, прежде чем оно используется, только если элемент является экземпляром (соответственно статическим) поля класс или интерфейс C и все следующие условия:

  • использование происходит в инициализаторе переменной экземпляра (соответственно статическом) C или в инициализаторе экземпляра (соответственно статическом)
    С.

  • использование не находится в левой части назначения.

  • использование через простое имя.

  • C-самый внутренний класс или интерфейс, заключающий использование.

поэтому, если использование находится в левой части задания, то это законно, так как второй больше не выполняется.