Создание объекта статическим способом
Может ли кто-нибудь объяснить, как Java выполняет этот код? Я имею в виду порядок выполнения каждого оператора.
public class Foo
{
boolean flag = sFlag;
static Foo foo = new Foo();
static boolean sFlag = true;
public static void main(String[] args)
{
System.out.println(foo.flag);
}
}
ВЫВОД:
false
Ответы
Ответ 1
- Начальная инициализация класса. Первоначально
foo
имеет значение null, а sFlag
- false
- Первый инициализатор статической переменной (
foo
) запускается:
- Создан новый экземпляр
foo
- Инициализатор переменной экземпляра для
flag
выполняется - в настоящее время sFlag
имеет значение false, поэтому значение flag
равно false
- Выполняется второй инициализатор статической переменной (
sFlag
), устанавливая значение true
- Инициализация классов завершена
-
main
выполняется, распечатывается foo.flag
, что неверно
Обратите внимание, что если sFlag
объявлено как final
, он будет рассматриваться как константа времени компиляции, после чего все ссылки на него будут в основном привязаны к true
, поэтому foo.flag
будет true тоже.
Ответ 2
foo
создается во время статической инициализации класса и до того, как sFlag был инициализирован, а значение по умолчанию для логического значения - false.
Подробнее см. JLS §12.4.
Ответ 3
Когда класс загружен, поля sFlag
и foo
инициализируются, но сначала инициализируется foo
!
поля flag
и sFlag
являются логическими и не могут быть нулевыми, поэтому по умолчанию есть false, а sFlag
все еще ложно, когда инициализируется foo
. flag = sFlag
после этого flag
является false.That это
Ответ 4
Общий порядок операций инициализации (после загрузки класса и перед первым использованием):
- Статические (классные) блоки кода, чтобы они отображались в коде,
- Блоки кода объекта, чтобы они отображались в коде (блоки инициализации и назначения).
- Конструкторы
Конечно, я не ссылаюсь на конструкторы и функции как блок кода выше.
Я не знаю, как насчет полей final static
. Похоже, что они следуют правилам полей static
, и они не могут быть указаны перед объявлением, несмотря на предыдущие комментарии, которые они инициализируются на этапе компиляции. Если они ссылаются до возникновения ошибки компиляции:
Example.java:8: illegal forward reference
System.err.println("1st static block j=" + j);
Может быть, поля final static
могут быть инициализированы и скомпилированы в файл класса, но это не является общим правилом, и до объявления еще не могут быть указаны.
Пример кода для проверки порядка инициализации:
class Example {
final static int j = 5;
{
System.err.println("1st initializer j=" + j);
}
static {
System.err.println("1st static block j=" + j);
}
static {
System.err.println("2nd static block j=" + j);
}
final static java.math.BigInteger i = new java.math.BigInteger("1") {
{
System.err.println("final static anonymous class initializer");
}
};
Example() {
System.err.println("Constructor");
}
static {
System.err.println("3nd static block j=" + j);
}
{
System.err.println("2nd initializer");
}
public static void main(String[] args) {
System.err.println("The main beginning.");
Example ex = new Example();
System.err.println("The main end.");
}
}
Вышеприведенный снимок кода печати:
1st static block j=5
2nd static block j=5
final static anonymous class initializer
3nd static block j=5
The main beginning.
1st initializer j=5
2nd initializer
Constructor
The main end.
Ответ 5
сначала статические поля должны запускаться и сначала в линию! поэтому в первой строке 4 и затем 5 будет выполняться так, чтобы foo сначала инициализировался, и поскольку мы знаем, что логические переменные инициализируются по умолчанию по умолчанию, поэтому сначала, так как инициализируется foo, поле флага имеет значение sflag, что false, а затем sfalsg становится истинным, не изменит флаг (нет никакого отношения), тогда, наконец, основные запуски и фальц печати, который является ложным!!!
Я надеюсь быть полезным! Будьте успешными