В каком порядке выполняются определения блоков и переменных инициализатора и т. Д.? (в яве) - PullRequest
10 голосов
/ 12 марта 2012

У меня проблемы с пониманием порядка, в котором происходит инициализация. это порядок, который я принял:

*Once per 
    1. Static variable declaration
    2. Static block
*Once per object
    3. variable declaration
    4. initialization block
    5. constructor

но по этому коду я явно ошибаюсь:

    class SomethingWrongWithMe
    {
        {
            b=0;         //no. no error here.
            int a = b;   //Error: Cannot reference a field before it is defined.
        }
        int b = 0;
    }

И ошибка исчезнет, ​​если я сделаю это:

    class SomethingWrongWithMe
    {
        int b = 0;
        {
            b=0;
            int a = b;   //The error is gone.
        }
    }

Я не могу понять, почему нет ошибки

    b=0;

Ответы [ 3 ]

4 голосов
/ 12 марта 2012

Спецификация языка Java (раздел 8.3.2.3) гласит, что вы можете использовать переменную в левой части выражения, то есть присваивать ей, прежде чем она будет объявлена, но вы не можете использовать ее в правой части.

Все переменные инициализируются значениями по умолчанию, затем запускаются явные инициализаторы и анонимные блоки в порядке, в котором они находятся в исходном файле.Наконец, конструктор вызывается.

Статика запускается только один раз при первом использовании класса.

Ошибка компиляции представляется правилом Java, а не чем-то, что обязательно имеет смысл в каждомслучай.

3 голосов
/ 12 марта 2012

Определения переменных не выполняются "до" блоков.Оба они выполняются одновременно, в порядке их определения

class SomethingWrongWithMe {
    {
        b = debug("block 1");
    }
    int b = debug("define");
    {
        b = debug("block 2");
    }
    private int debug(String str) {
        System.out.println(str);
        return 0;
    }
}

Вывод

block 1
define
block 2
1 голос
/ 12 марта 2012

Прежде всего, ваши предположения более или менее верны, за исключением того факта, что объявления (с инициализацией, такие как int b = 0) и блоки инициализатора экземпляра выполняются в том порядке, в котором они записаны.

int b = 0;   // executed first

{
    b = 1;   // executed second
}

int a = b;   // executed third

Также обратите внимание, что объявление , т.е. int b не выполнено .Объявление просто объявляет существование переменной.

Что касается полученной вами ошибки (или, скорее, ошибки, которую вы не получили), я согласен, что онавыглядит странноЯ предполагаю, что компилятор имеет дело со ссылкой на переменную в выражении и присвоением ей значения различными способами.При записи в переменную в инициализаторе экземпляра он просто проверяет наличие переменной, а при чтении из нее требует, чтобы она была объявлена ​​над блоком инициализатора экземпляра.Я посмотрю, смогу ли я найти ссылку на это в JLS.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...