Создание объекта статическим способом
Может ли кто-нибудь объяснить, как 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
5 ответов
- Инициализация класса начинается. Первоначально,
foo
является нулевым иsFlag
ложно - Первый инициализатор статической переменной (
foo
) работает:- Новый экземпляр
Foo
создано - Инициализатор переменной экземпляра для
flag
выполняет - в настоящее времяsFlag
ложно, поэтому значениеflag
ложно
- Новый экземпляр
- Инициализатор второй статической переменной (
sFlag
) выполняется, устанавливая значение в true - Инициализация класса завершена
main
работает, распечаткаfoo.flag
что неверно
Обратите внимание, что если sFlag
были объявлены final
он будет рассматриваться как константа времени компиляции, после чего все ссылки на него будут в основном true
, так foo.flag
было бы правдой тоже.
foo
создается во время статической инициализации класса и до инициализации sFlag, а логическое значение по умолчанию - false.
- Класс загружен
Foo инициализируется к экземпляру
2.a Флаг элемента экземпляра инициализируется значением sFlag (
false
по умолчанию)- sFlag инициализируется как true
Пожалуйста, обратитесь к JLS §12.4 для более подробной информации.
Когда класс загружен, sFlag
а также foo
поля инициализируются, но foo
инициализируется первым!
поля flag
а также sFlag
являются булевыми и не могут быть нулевыми, поэтому по умолчанию вы ложны и sFlag
все еще ложь, когда foo
инициализируется. flag = sFlag
после этого flag
это ложь.
Общий порядок операций инициализации (после загрузки класса и перед первым использованием):
- Статические (классовые) кодовые блоки в порядке их появления в коде,
- Код объекта блокируется по порядку его появления в коде (блоки инициализации и присваивания).
- Конструкторы
Конечно, я не называю тело конструкторов и функций как блок кода выше.
Я не знаю как насчет 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.
Сначала должны запуститься статические поля, а в начале - встроенные! поэтому сначала выполняется строка 4, а затем 5, поэтому сначала инициализируется foo, и, как мы знаем, булевы переменные по умолчанию инициализируются как false, так что сначала, когда инициализируется foo, поле флага равно sflag, что ложно, а затем sfalsg становится истинным, что не будет менять флаг (здесь нет никакого отношения), а затем, наконец, запустится и напечатает Falg, который имеет значение false!!! Я надеюсь быть полезным! Быть успешным