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

Я заметил что-то в статических инициализаторах, что может быть ошибкой в ​​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;
}

person S E    schedule 07.05.2013    source источник
comment
Я считаю, что [ответ на аналогичный вопрос] [1] отвечает на этот вопрос лучше, чем я могу. Это странное поведение, но не ошибка. Он делает то, что должен делать. [1]: stackoverflow.com/a/10035928/348975   -  person emory    schedule 07.05.2013
comment
Я не уверен, что это так, статические инициализаторы предназначены для инициализации переменных из их значения по умолчанию. то есть статический int v = 1; эквивалентен static int v; статический {v = 1;}   -  person S E    schedule 07.05.2013
comment
@Dukeling Я написал свой комментарий как ответ, и StackOverflow определил, что мой ответ был тривиальным (я думаю, что это означает, что он слишком короткий), и автоматически преобразовал его в комментарий, но, очевидно, испортил ссылки.   -  person emory    schedule 07.05.2013
comment
Выдает ошибку: какая ошибка?   -  person Raedwald    schedule 19.01.2016


Ответы (1)


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

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

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

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

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

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

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

person zw324    schedule 07.05.2013
comment
Хорошо, я понимаю, что это часть спецификации, но это кажется очень странным указывать - person S E; 07.05.2013
comment
Иногда мне кажется, что Java нужно больше, чем просто спецификация, но и еще одна книга, объясняющая решения, которые она принимает. Я надеюсь, что кто-то может пролить больше света на это, но спецификация — лучшее, что я могу найти. - person zw324; 07.05.2013