Всегда ли выполняется статический код при первом использовании класса? - PullRequest
12 голосов
/ 07 июля 2010

Наше приложение использует код инициализации, который зависит от статического кода заказа, и мне интересно, будет ли этот порядок согласован во всех 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 всегда выполняется статический код при первом использовании класса?

Ответы [ 8 ]

18 голосов
/ 07 июля 2010

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


Да, это гарантируется спецификацией языка. С раздел 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).
  • Т является класс верхнего уровня и утверждение оператор (§14.10) лексически вложенный
4 голосов
/ 07 июля 2010

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

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

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

* 1006.*
3 голосов
/ 07 июля 2010

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

2 голосов
/ 07 июля 2010

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

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

1 голос
/ 07 июля 2010

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

1 голос
/ 07 июля 2010

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

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

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

0 голосов
/ 07 июля 2010

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

0 голосов
/ 07 июля 2010

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

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