Импорт не коррелирует с инструкциями в скомпилированном коде. Они устанавливают псевдонимы для использования только во время компиляции.
Существуют некоторые рефлексивные методы, которые позволяют загружать класс, но еще не инициализировать, но в большинстве случаев вы можете предположить, что всякий раз, когда на класс ссылается, он инициализируется.
Инициализаторы статических элементов и статические блоки выполняются так, как если бы они были одним блоком статического инициализатора в порядке исходного кода.
На объект, на который ссылается статическая переменная-член, жесткие ссылки, пока класс не выгружен. Обычный ClassLoader
никогда не выгружает класс, но те, которые используются серверами приложений, делают в правильных условиях. Однако это сложная область, которая является источником многих трудно диагностируемых утечек памяти - еще одна причина не использовать глобальные переменные.
В качестве (тангенциального) бонуса необходимо рассмотреть один сложный вопрос:
public class Foo {
private static Foo instance = new Foo();
private static final int DELTA = 6;
private static int BASE = 7;
private int x;
private Foo() {
x = BASE + DELTA;
}
public static void main(String... argv) {
System.out.println(Foo.instance.x);
}
}
Что будет печатать этот код? Попробуйте, и вы увидите, что он печатает «6». Здесь есть несколько вещей, и один из них - порядок статической инициализации. Код выполняется так, как если бы он был написан так:
public class Foo {
private static Foo instance;
private static final int DELTA = 6;
private static int BASE;
static {
instance = null;
BASE = 0;
instance = new Foo(); /* BASE is 0 when instance.x is computed. */
BASE = 7;
}
private int x;
private Foo() {
x = BASE + 6; /* "6" is inlined, because it's a constant. */
}
}