Статический код всегда выполняется, когда мы используем класс впервые?

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

Вот образец того, что я имею в виду:


public class Main {

    static String staticVar = "init_value";

    public static void main(String[] args) {

        System.out.println(A.staticVar);
        staticVar = "mainValue";
        System.out.println(A.staticVar);
    }
}

public class A {
    static String staticVar = Main.staticVar;
}

даст:

init_value
init_value

и


public class Main {

    static String staticVar = "init_value";

    public static void main(String[] args) {

        // System.out.println(A.staticVar);
        staticVar = "mainValue";
        System.out.println(A.staticVar);
    }
}

public class A {
    static String staticVar = Main.staticVar;
}

даст (на моей среде):

mainValue

Подводя итоги, через весь JVMs, статический код всегда выполняется, когда мы используем класс впервые?

12
задан matthieus 7 July 2010 в 15:02
поделиться

8 ответов

РЕДАКТИРОВАТЬ: Несмотря на все заверения ниже, если вы думаете полагаться на такие вещи , Я бы очень постарался реорганизовать ваш код, чтобы он не всплывал. Хотя гарантированно работает, это также может сделать ваш код очень хрупким. Тот факт, что статические инициализаторы вызываются «невидимо», делает их относительно сложными для анализа и отладки.


Да, это гарантируется спецификацией языка. Из раздела 8.7 спецификации:

Любые статические инициализаторы, объявленные в классе, выполняются при инициализации класса и, вместе с любыми инициализаторами полей (§8.3.2) для переменных класса, могут использоваться для инициализации переменных класса класса (§12.4).

StaticInitializer: static Блок

Это ошибка времени компиляции, когда статический инициализатор может завершить работу внезапно (§14.1, §15.6) с проверенным исключением (§11.2). Если статический инициализатор не может нормально завершиться, это ошибка времени компиляции (§14.21).

Статические инициализаторы и инициализаторы переменных класса выполняются в текстовом порядке.

И из раздела 12.4 :

Инициализация класса состоит из выполнение его статических инициализаторов и инициализаторы для статических полей объявлен в классе. Инициализация интерфейса состоит из выполнения инициализаторы для объявленных полей в интерфейсе.

Перед классом инициализирован, его прямой суперкласс должен быть инициализирован, но интерфейсы реализуется классом, не обязательно инициализирован. Точно так же суперинтерфейсы интерфейса нужны не инициализироваться до интерфейс инициализирован.

Класс или тип интерфейса T будет инициализируется непосредственно перед первое появление любого из следующее:

  • T - это класс, а экземпляр T - созданный.
  • T - это класс и статический вызывается метод, объявленный T.
  • A статическое поле, объявленное T, является назначенный.
  • Статическое поле, объявленное T используется, и поле не постоянная переменная (§4.12.4).
  • T - это класс верхнего уровня и утверждение оператор (§14.10), лексически вложенный
18
ответ дан 2 December 2019 в 05:14
поделиться

Статические инициализаторы (например, ваши объявления staticVar) всегда выполняются при первом использовании класса.

Статические методы выполняются только при их вызове. В вашем случае это происходит потому, что статический метод void main(String[] args) является точкой входа в ваше приложение. Но если бы вы определили другой статический метод, то он не был бы вызван.

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

static {
  // some initialisation code here
}
4
ответ дан 2 December 2019 в 05:14
поделиться

Это должно быть одинаково на всех платформах. См. спецификацию JVM : http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html#19075

3
ответ дан 2 December 2019 в 05:14
поделиться

Статический блок всегда будет запускаться первым, а не только в первый раз ... Перед выполнением любого блока кода JVM сначала выполняет статический блок кода , а затем только он запускает блок кода, как он был разработан ...

0
ответ дан 2 December 2019 в 05:14
поделиться

Цитата из спецификации Java:

Инициализация класса состоит из выполнения его статических инициализаторов и инициализаторов для статических полей объявленных в классе. Инициализация интерфейса состоит из выполнения инициализаторов для полей, объявленных в интерфейсе.

2
ответ дан 2 December 2019 в 05:14
поделиться

Да, я полагаю, что в этом смысл по определению.

0
ответ дан 2 December 2019 в 05:14
поделиться

Да, согласно Спецификации языка Java статический код всегда выполняется в одном порядке на всех (совместимых) JVM.

8.7 Статические инициализаторы

Статические инициализаторы и инициализаторы переменных класса выполняются в текстовом порядке.

1
ответ дан 2 December 2019 в 05:14
поделиться

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

1
ответ дан 2 December 2019 в 05:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: