Создание объекта статическим способом

Может ли кто-нибудь объяснить, как 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.

  1. Класс загружен
  2. Foo инициализируется к экземпляру

    2.a Флаг элемента экземпляра инициализируется значением sFlag (false по умолчанию)

  3. sFlag инициализируется как true

Пожалуйста, обратитесь к JLS §12.4 для более подробной информации.

Когда класс загружен, sFlag а также foo поля инициализируются, но foo инициализируется первым!
поля flag а также sFlag являются булевыми и не могут быть нулевыми, поэтому по умолчанию вы ложны и sFlag все еще ложь, когда foo инициализируется. flag = sFlag после этого flag это ложь.

Общий порядок операций инициализации (после загрузки класса и перед первым использованием):

  1. Статические (классовые) кодовые блоки в порядке их появления в коде,
  2. Код объекта блокируется по порядку его появления в коде (блоки инициализации и присваивания).
  3. Конструкторы

Конечно, я не называю тело конструкторов и функций как блок кода выше.

Я не знаю как насчет 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!!! Я надеюсь быть полезным! Быть успешным

Другие вопросы по тегам