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

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

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

Вот пример того, что я имею в виду:


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

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

4b9b3361

Ответ 1

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


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

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

StaticInitializer: static Блок

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

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

И из раздел 12.4:

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

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

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

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

Ответ 2

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

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

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

static {
  // some initialisation code here
}

Ответ 4

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

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

Ответ 6

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

Ответ 7

Да, я считаю, что это будет точка по определению.

Ответ 8

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